Topic = 어댑터 패턴의 의도와 Kotlin 예제로 실습해보기.
🔑 Purpose
- Adapter라는 중간 클래스를 통해 서로 다른 인터페이스를 가진 클래스들이 함께 작동할 수 있도록 하여 새로운 시스템을 도입하더라도 기존의 인터페이스를 변경하지 않고도 새로운 기능을 추가할 수 있도록 한다.
Adapter 패턴 개념
Adapter 패턴은 120V 돼지코 콘센트에 220V 플러그를 지닌 전자기기를 사용하기 위해 어뎁터를 사용하는 것과 같이 기존 클래스를 사용하고 싶지만, 그 인터페이스가 다른 코드와 호환되지 않을 때 사용할 수 있다.
즉, Client가 사용하고 있는 Target(120V 콘센트)에 호환되지 않는 Adaptee(220V 플러그)를 Target에 만족시키기 위해 Adapter를 사용하는 것처럼 Adapter 패턴의 의도는 호환성 및 확장성이다.
유지 관리 측면에서도, 충분히 테스트 되어 버그가 적던 기존의 코드에 새로운 API를 추가하려고 할 때, 기존 클래스의 코드를 수정하는 방식보다 어댑터를 통해 새로운 인터페이스를 맞추어 버그가 발생하더라도 Adapter 클래스를 중점적으로 살펴보며 수정할 수 있다.
120V에 220V 어뎁터를 덮어씌우는 것과 같이 Wrapper 패턴이라고 부르기도 한다.
위임을 통한 어댑터 vs 상속을 통한 어댑터
🔀예제 코드에 앞서, Adapter 패턴을 적용하기 위한 방법은 상속을 통한 어댑터 패턴과 위임을 통한 어댑터 패턴으로 나누어 볼 수 있다. 각각의 장단점이 있지만 대부분의 경우 위임을 통한 어댑터가 객체지향 설계 원칙에 더 적합하다.
- 구체적인 Adaptee에 의존하기보다, 인터페이스에 의존할 수 있다 - DIP
- 상속을 사용할 경우, Adaptee의 모든 특성을 Adapter가 그대로 가져와야 하므로 LSP를 위반할 가능성이 높다.
[ 예제 코드 ]
USB-C 타입의 충전기와 USB-C to Lightning 어뎁터를 통해 라이트닝 USB 충전 타입의 휴대폰을 충전하는 예제.
[ Adaptee ]
class ChargerTypeC {
fun connection() {
println("C 타입 USB 를 통해 전류가 흐른다.")
}
}
- Adaptee는 Client와 Target 입장에서 호환되지 않는 인터페이스 형식으로, Adapter를 통해 Target 형식으로 변환 되어야 하는 것이다.
[ Target ]
interface ChargerTypeLightning {
fun connectionLightning()
}
- Client가 사용할 인터페이스로, Adaptee가 변환되어야 하는 인터페이스 형식을 지정해주는 것. 라이트닝 USB 타입의 핸드폰을 충전하기 위해 필요한 메서드를 결정한다.
[ Adapter ]
// 위임을 통한 Adapter 패턴
class TypeCToLightningAdapter(
private val chargerTypeC: ChargerTypeC
) : ChargerTypeLightning {
override fun connectionLightning() {
chargerTypeC.connection()
println("C to lightning Adapter 연결")
println("Lightning 타입 USB 를 통해 전류가 흐른다.")
}
}
- Adaptee을 생성자로 위임 받아, 필요한 메서드만 Target에 형식에 맞춰 지원한다.
[ 구체 Client ]
class MyPhone {
fun charged(charger: ChargerTypeLightning ) {
charger.connectionLightning()
}
}
- Target의 메서드를 적용할 대상 정의.
[ Client 접근( 사용 ) ]
fun adapterPatternTest() {
val myPhone = MyPhone()
// 1. 위임을 사용한 어댑터 패턴
val myCharger = ChargerTypeC()
val myAdapterCharger = TypeCToLightningAdapter(myCharger)
myPhone.charged(myAdapterCharger)
// 2. 상속을 통한 어댑터 패턴
val myAdapterChargerV2 = TypeCToLightningAdapterV2()
myPhone.charged(myAdapterChargerV2)
}
[ A. 오늘 복습한 내용 / B. 다음에 학습할 내용 ]
A. 무분별한 상속은 LSP 위반할 수 있다.
B. 탬플릿 메서드 패턴
[Reference]
'웹개발 - Back 관련 > Architecture' 카테고리의 다른 글
[ GOF ] 싱글톤 패턴, object - Singleton Pattern with Kotlin (6) | 2024.10.08 |
---|---|
[ GOF ] 팩토리 매서드 패턴 - Factory Method Pattern with Kotlin (0) | 2024.09.11 |
[ GOF ] 전략 패턴 - Strategy Pattern with Koltin (0) | 2024.09.10 |
[ GOF ] 탬플릿 메서드 패턴 - Template method with Kotlin (0) | 2024.09.09 |
[ GOF ] 반복자 패턴 - Iterator Pattern with Kotlin (2) | 2024.09.09 |