의도
- 어댑터는 호환되지 않는 인터페이스를 가진 객체들이 협업할 수 있도록 하는 구조적 디자인 패턴
문제
- XML 데이터를 받아오는 주식 서비스의 값을 사용하고 싶다. 그런데 분석 라이브러리는 JSON 형식 데이터로만 작동하게 된다.
- XML 형식의 데이터를 받아오도록 라이브러리를 변경할 수 있으나, 데이터가 손상될 수 있고, 혹은 아예 소스코드 접근이 불가능한 경우도 발생할 수 있다.
해결책
- 코드와 직접 작동하는 분석 라이브러리의 모든 클래스에 대한 XML->JSON 변환 어댑터를 제작
- 어댑터 제작 이후 어탭터를 통해서만 해당 라이브러리와 통신하도록 코드를 조정
- 어댑터는 호출을 받으면 XML을 JSON으로 변환한 후 호출을 래핑된 분석 객체의 적절한 메서드에 전달
구조
class Target {
public request(): string {
return 'Target: The default target\'s behavior.';
}
}
class Adaptee {
public specificRequest(): string {
return '.eetpadA eht fo roivaheb laicepS';
}
}
class Adapter extends Target {
private adaptee: Adaptee;
constructor(adaptee: Adaptee) {
super();
this.adaptee = adaptee;
}
public request(): string {
const result = this.adaptee.specificRequest().split('').reverse().join('');
return `Adapter: (TRANSLATED) ${result}`;
}
}
function clientCode(target: Target) {
console.log(target.request());
}
console.log('Client: I can work just fine with the Target objects:');
const target = new Target();
clientCode(target);
const adaptee = new Adaptee();
console.log('Client: The Adaptee class has a weird interface. See, I don\'t understand it:');
console.log(`Adaptee: ${adaptee.specificRequest()}`);
console.log('Client: But I can work with it via the Adapter:');
const adapter = new Adapter(adaptee);
clientCode(adapter);
적용
- 기존 클래스를 사용하고 싶지만 인터페이스가 호환되지 않을 때 사용
직접 짠 코드와 레거시 클래스, 타사의 클래스등과의 변환기 역할을 하는 중간 레이어 클레스 제작
- 부모 클래스에 추가할 수 없는 공통기능들이 필요한 자식 클래스들을 재사용하려는 경우에 사용
각 자식 클래스를 확장해서 누락된 기능들을 새 자식 클래스에 넣을 수 있지만, 공통기능을 각 클래스마다 복제해야 하는 문제 발생
어댑터 클래스에 누락된 기능을 넣고, 객체를 래핑해 필요한 기능을 동적으로 할당 가능
구현 방법
- 호환되지 않는 인터페이스가 있는 클래스가 2개이상 있는지 확인
- 클라이언트 인터페이스를 선언하고 서비스와 통신하는 방법을 기술해둠
- 어댑터 클래스를 생성해 클라이언트 인터페이스를 따르게 함
- 서비스 객체에 reference를 저장하기 위해 어댑터 클래스에 필드를 추가
- 클라이언트 인터페이스의 모든 메서드를 어댑터 클래스에서 하나씩 구현
어댑터는 인터페이스, 데이터 변환 형식만 처리해야 하며, 실제 작업의 대부분은 서비스 객체가 진행해야 함
- 클라이언트들은 클라이언트 인터페이스를 통해 어댑터 사용
장단점
- 프로그램의 비지니스 로직에서 인터페이스, 데이터 변환 코드를 분리해 단일 책임 원칙, 개방/폐쇄 원칙 준수
- 다수의 새로운 인터페이스와 클래스들을 도입해야 하기에 코드의 전반적인 복잡성 증가
서비스 클래스를 변경 하는 것이 간단할 때도 있음
출처:
https://refactoring.guru/ko/design-patterns/adapter