어댑터 패턴(Adapter Pattern) ; OCP, 추상화
한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다.
어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 사용할 수 있다.
객체 어댑터 패턴 vs 클래스 어댑터 패턴
객체 어댑터 패턴
‘구성(Composition)’ 을 사용하여 인터페이스를 변경하는 경우
- 구성을 사용하므로, Adapter 에서 변환 로직이 복잡한 경우, 다소 코드가 길어질 수 있음
클래스 어댑터 패턴
‘상속(Inheritance)’ 을 사용하여 인터페이스를 변경하는 경우
- 유연성이 떨어지지만, 상속의 장점인 ‘중복제거’ 측면에서 생산성은 높을 수 있음
어떤 것을 사용?
경우에 따라 다 다르다.
다만, 유연성 vs 코드중복 관점에서는 대체로 유연성이 더 좋은 설계를 선호하기 때문에 객체 어댑터 패턴으로 구현하는 것이 좋다.
어댑터 패턴 장단점
장점
- Adapter 의 가장 큰 장점은 제공자 / 클라리언트 둘 다 코드를 변경하지 않아도 된다는 점
- Adapter만 새로 작성하면 됨
- 재활용성이 높음(Adapter 규격에 맞는 객체는 모두 사용 가능)
단점
- 구성요소를 위해 클래스를 증가시켜야 하기 때문에 복잡도가 증가할 수 있음
- 클래스 어댑터 패턴을 사용한다면, 상속을 사용하기 때문에 유연성이 떨어짐
일본의 전자제품을 한국에서 사용하게 변경해주는 Adapter 설계
책의 예제가 조금 이해하기 난해해서, 실생활을 추상화하여 예시를 하나 설계해보았다.
일본에서 산 전자제품(110v 정격전압)을 한국(220v 정격전압)에서 사용할 수 있도록 해주는 어뎁터를 실제 설계해보았다.
JPElectronicProduct Interface
일본의 전자제품 연결을 위한 Interface
1 | public interface JPElectronicProduct { |
JPAirConditioner Class
일본에서 구매한 에어컨 클래스, JPElectronicProduct 를 구현하고 있다.
1 | public class JPAirConditioner implements JPElectronicProduct { |
KRElectronicProduct Interface
한국의 전자제품 연결을 위한 Interface
1 | public interface KRElectronicProduct { |
KRRefrigerator Class
한국에서 구매한 냉장고 클래스, KRElectronicProduct 를 구현하고 있다.
1 | public class KRRefrigerator implements KRElectronicProduct { |
Adapter 클래스
일본에서 구매한 전자제품을 한국의 정격전압과 연결하게 해주는 Adapter 클래스
1 | public class AdapterForKoreaElectronicProduct implements KRElectronicProduct { |
테스트 코드
1 | class AdapterTest { |
Spring 속 어댑터 패턴 - MultiValueMapAdapter
Spring의 util 패키지에 (Key, List) 로 구성되는 MultiValueMap 이란 자료구조가 존재한다.
MultiValueMapAdapter 는 JavaSE 의 java.util.Map 컬렉션 을 MultiValueMap으로 사용하게 끔 도와주는 어댑터이다.
따라서 Map<K, List<V>>
구조의 Map을 MultiValueMap
타입으로 변환하여 사용이 가능하게 한다.
1 | package org.springframework.util; |
생각해보자
데코레이터 vs 어댑터
앞서 다루었던 데코레이터 패턴도 어느정도 어댑터 패턴과 공통점이 있는 것 같아서 헷갈리기 시작했다.
따라서 어댑터 패턴과 데코레이터 패턴의 정의로부터 목적을 다시 상기하며 비교해보았다.
공통점
- 둘 다 어떤 관점으로든 특정 객체를
Wrapping
하고 있다.
차이점
- 어댑터 : 특정 인터페이스로 변환하기 위한 목적이다.
- 데코레이터 : 특정 기능이나 속성을 추가하기 위한 목적이다.
변화와 책임부여 관점에서 바라 본 디자인 패턴
디자인 패턴을 계속 공부하다보니 대부분의 경우
‘변화할 가능성이 있는 부분을 별도 객체로 분리하고, 그 객체에 변화에 대한 책임을 부여한다.’ 라는 차원에서 접근한다.
그리고 그 방법에 따라 여러 디자인 패턴으로 나눌 수 있는 것 같다. 이런 사실 때문에 디자인 패턴은 단독으로 사용되는 경우가 드물며, 여러 디자인 패턴을 결합해서 사용하는 경우도 많은 것 같다.
또한, 어떤 코드를 봤을 때 ‘아 이건 OOO 디자인 패턴을 사용했다.’ 라고 단정지을 수 있는 경우가 많지 않다.
따라서, 어떤 디자인 패턴을 학습할 때 조심해야 되는 것은 ‘어떤 기술과 구현 방법을 썼기 때문에 이 디자인 패턴은 OOO 다’ 라고 단정지으면 안된다는 생각이 들었다.
가장 중요한 것은 ‘어떤 문제가 발생했고, 이 문제를 어떻게 해결하는 것이 더 좋은 설계인 지’ 관점에서 디자인 패턴을 학습해야 한다.