🎈 어댑터 패턴 (Adapter Pattern)
• 호환되지 않는 인터페이스를 가진 두 개의 클래스를 함께 사용할 수 있게 한다.
• 상속 보다는 위임하는 형태 권장
상속은 실수로라도 접근할 수 있기에 데이터를 보호하지 못할 수 있다.
• 예시) 라이브러리 호환, 데이터 변환, 외부 API 통합, 로그 변환
• 디자인 패턴 중 구조 패턴에 속한다.
[예제 코드]
#include <iostream>
// 기존의 온도 변환 클래스
class FahrenheitTemperature {
public:
FahrenheitTemperature(double temp) : temperature(temp) {}
double getTemperature() { return temperature; }
private:
double temperature;
};
// 새로운 온도 변환 인터페이스
class CelsiusTemperature {
public:
virtual double getTemperature() = 0;
};
// 어댑터 클래스
class FahrenheitToCelsiusAdapter : public CelsiusTemperature {
public:
FahrenheitToCelsiusAdapter(FahrenheitTemperature& fahrenheitTemp) : fahrenheitTemperature(fahrenheitTemp) {}
double getTemperature() override {
// 화씨를 섭씨로 변환
return (fahrenheitTemperature.getTemperature() - 32) * 5.0 / 9.0;
}
private:
FahrenheitTemperature& fahrenheitTemperature;
};
void main() {
FahrenheitTemperature fahrenheitTemp(32.0);
std::cout << "Fahrenheit temperature: " << fahrenheitTemp.getTemperature() << "°F" << std::endl;
// 어댑터 사용
CelsiusTemperature* celsiusTemp = new FahrenheitToCelsiusAdapter(fahrenheitTemp);
std::cout << "Celsius temperature: " << celsiusTemp->getTemperature() << "°C" << std::endl;
}
FahrenheitToCelsiusAdapter 클래스는 CelsiusTemperature 인터페이스를 구현하고,
그 안에서 화씨를 섭씨로 변환하는 코드 제공
🎈 어댑터 패턴 장단점
+ 호환성: 새로운 코드 통합할 때, 기존 코드를 변경하지 않고 호환성 제공
+ 재사용성: 기존 코드 변경이 없으므로 재사용성 up
+ 단일 책임 원칙 준수: 새로운 클래스가 인터페이스에만 집중하면 된다.
- 호출 체인으로 인해 약간의 오버헤드 발생
- 복잡성 증가: 어댑터 클래스로 인한 코드 복잡도 증가
[예제 코드] - 어댑터 패턴 적용 X
#include <iostream>
class LegacyLibrary {
public:
void legacyRequest() {
std::cout << "Legacy..." << std::endl;
}
};
void main() {
LegacyLibrary legacy;
legacy.legacyRequest();
}
LegacyLibrary라는 클래스와 legacyRequest 메서드로 작업을 수행하고 있다.
이제 새로운 라이브러리가 도입되었다고 가정해보자.
두 라이브러리의 인터페이스가 호환되지 않는다.
어댑터 패턴을 사용하여 기존 코드에서 새 라이브러리를 사용할 수 있어야 한다.
[예제 코드] - 어댑터 패턴 적용 O
#include <iostream>
class LegacyLibrary {
public:
void legacyRequest() {
std::cout << "Legacy..." << std::endl;
}
};
// 새 라이브러리 인터페이스
class NewLibrary {
public:
void newRequest() {
std::cout << "New..." << std::endl;
}
};
// 어댑터 클래스
class NewLibraryAdapter {
public:
NewLibraryAdapter(NewLibrary& newLib) : newLibrary(newLib) {}
void legacyRequest() {
newLibrary.newRequest();
}
private:
NewLibrary& newLibrary;
};
void main() {
LegacyLibrary legacy;
legacy.legacyRequest();
// 어댑터 사용
NewLibrary newLib;
NewLibraryAdapter adapter(newLib);
adapter.legacyRequest();
}
NewLibraryAdapter 클래스로
legacyRequest 메서드를 newRequest 메서드와 연결 하였다.
🎈 다른 디자인 패턴과 비교
연결하는 관점에서 브릿지 패턴과 유사하다.
브릿지 패턴은 추상화와 구현을 분리하여 독립적으로 확장할 수 있게 한다.
즉, 인터페이스와 구현을 연결하는데 사용
데코레이터 패턴은 객체에 동적으로 새로운 기능을 변경/확장할 때 사용
어댑터는 새로운 기능을 추가하기 보다 인터페이스 환경 제공
팩토리 패턴은 객체 생성에 중점을 두는데
객체 생성 방법을 하위 클래스에 위임하고, 구체적인 객체 생성을 지연시킨다.
• 전략 (Strategy)
전략 패턴은 알고리즘을 런타임에 변경하고 동적으로 선택할 수 있도록 하는데 사용
알고리즘을 캡슐화하고 교환 가능하게 만든다.
사용목적 차이가 있다.
Adapter는 A 클래스와 B 클래스간 인터페이스 불일치를 해결
Proxy는 두 객체 사이에서 Proxy객체를 두어 객체 사이의 Decouple
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] GRASP 객체지향 (2) | 2024.11.12 |
---|---|
[객체 지향] IS-A 관계와 HAS-A 관계 (2) | 2024.10.21 |
💻 디자인 패턴(Design Pattern)이란? (6) | 2024.08.02 |
[디자인패턴] 체인 패턴 (Chain of Responsibility, 책임 연쇄) (4) | 2024.07.31 |
객체 지향 프로그래밍 5대 원칙 [SOLID] (40) | 2023.11.19 |
댓글