디자인 패턴 중 Adapter 패턴에 대해 설명합니다.
개념
현실세계 Adapter와 동일한 개념으로 호환 불가능한 인터페이스를 가진 객체들을 협업 가능하도록 하는 구조 패턴입니다. 다음과 같은 장점이 있습니다.
- Single Responsibility Principle: 협업을 위한 데이터 변환 로직을 비즈니스 로직과 분리하여 책임을 분산합니다.
- Open-Closed Principle: 객체의 타입이 늘어나도 비즈니스 로직이 수정될 필요가 없습니다. 클래스 확장을 통해 해결합니다.
- Dependency Inversion Principle: 구체적인 구현 객체에 의존하지 않고 인터페이스에 의존합니다.
- 각 인터페이스 간 호환 가능하도록 데이터 변환하는 로직을 캡슐화합니다.
- 로직 변경이 불가능한 서드파티 라이브러리와 호환이 가능해집니다.
Adapter 패턴을 구현하는 방법은 Object Adapter와 Class Adapter가 있습니다.
Object Adapter
클라이언트 코드에서 의존할 인터페이스를 정의합니다. 그리고 이를 구현하는 클래스가 바로 Adapter입니다. Adapter 클래스에는 adaptee라는 속성이 있는데, 데이터를 변환해 실제 로직을 수행해야 하는 객체를 할당하는 속성입니다.
클라이언트가 Adapter의 메소드를 호출하면 데이터를 변환하는 작업을 거친 후 해당 데이터를 기반으로 adaptee의 메소드를 호출합니다. 실제 비즈니스 로직은 adaptee에게 위임하고 adapter는 변환에만 집중합니다.
Class Adapter
협업이 필요한 두 클래스를 다중상속 받습니다. 클라이언트 코드는 기존에 존재하는 클래스에 의존하여 Adapter든 기존에 존재하는 클래스든 동일하게 취급합니다. Object Adapter와 마찬가지로 클라이언트가 Adapter의 메소드를 호출하면 데이터를 변환하는 작업을 거친 후 해당 데이터를 기반으로 adaptee의 메소드를 호출합니다.
적용예시
코인 거래소 애플리케이션을 개발 중이라고 가정합니다. 기존 코드는 JSON 데이터 포맷으로 데이터를 받아 차트를 만들어 왔는데 새로운 서드파티 차트 라이브러리를 도입할 계획입니다. 문제는 이 라이브러리는 XML 데이터 포맷을 기반으로 합니다. Adapter 패턴을 사용하면 이를 해결할 수 있습니다.
class AbstractChartAdapter:
def render(self, data): ...
class XMLChart:
def render(self, data): ...
class XMLChartAdapter:
def __init__(self, adaptee: XMLChart) -> None:
self.adaptee = adaptee
def _convert_to_xml_format(self, data):
# convert
print("convert")
return data
def render(self, data):
xml_data = self._convert_to_xml_format(data)
return self.adaptee.render(xml_data)
XMLChart 객체를 래핑 하는 Adapter를 정의합니다. 해당 Adapter는 데이터를 XML 포맷으로 변경하여 XMLChart 객체 메소드를 호출하여 결과를 반환합니다.
참조
'객체 지향 > 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - Composite (0) | 2023.10.22 |
---|---|
디자인 패턴 - Bridge (0) | 2023.10.21 |
디자인 패턴 - Singleton (0) | 2023.10.11 |
디자인 패턴 - Prototype (0) | 2023.10.09 |
디자인 패턴 - Builder (0) | 2023.10.09 |