[디자인패턴] 어댑터 패턴
어댑터 패턴
정의
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
-GoF design pattern
어댑터 패턴(Adapter Pattern)은 클래스의 인터페이스를 클라이언트가 원하는 형태의 또 다른 인터페이스로 변환해준다.
구조
Client
클라이언트 입장에서는 새로운 기능을 사용하기 위해 Adaptee의 specificRequest()
써야 되는데 기존에 사용하던 request()
로 접근하고 싶다.
Target
기존에 사용하던 인터페이스라고 생각하면 된다. 새로운 인터페이스(Adaptee)를 어댑터를 사용해서 Target인터페이스를 사용하듯이 하는 것이 목표이다.
Adapter
새로운 인터페이스인 Adaptee를 기존에 사용하던 Target인터페이스처럼 사용할 수 있도록 변환해주는 역할을 수행한다.
Adaptee
새로운 인터페이스로 기존에 사용하던 Target인터페이스와 다르다.
특징
장점
어댑터 패턴을 사용함으로써 기존 클래스를 수정하지 않고도 클라이언트에서 새로운 인터페이스를 사용할 수 있게 된다.
단점
어댑터 클래스를 새로 작성해야 하기 때문에 소스 코드가 늘어나고 코드의 복잡도가 늘어난다.
어댑터가 중간에 데이터를 변환하는 과정에서 추가적인 처리 시간과 오버헤드가 발생할 수 있다.
필요성
어떤 회사의 시스템이 있다고 해보자. 그런데 새로운 기능을 구현하기 위해 다른 업체에서 제공하는 클래스 라이브러리를 사용해야 하는 상황이 생겼다.
이 상황에서 만약 기존 시스템의 인터페이스와 새로운 업체에서 사용하는 인터페이스가 다르면 호환성 문제가 발생한다.
이때 어댑터 패턴을 사용하면 이를 해결할 수 있다.
예시
우리는 핸드폰을 사용하고 있다. 이 핸드폰은 두 가지 기능이 있는데 화면을 보여주는 기능과 전원을 종료하는 기능이다.
이를 코드로 나타내보면 아래와 같다.
Phone Class (Target)
Galaxy (Phone의 구현 객체)
- 화면 보여주는 기능 :
display()
- 전원을 종료하는 기능 :
shutDown()
이 상황에서 태블릿 기기를 선물 받았다고 해보자.
태블릿 클래스 코드는 아래와 같다.
Tablet (Adaptee)
그런데 우리는 태블릿 기기를 사용하려면 여러가지 기능을 새로 배워야 한다.
그래서 우리는 태블릿을 기존에 사용하던 핸드폰과 동일한 인터페이스로 사용할 수 있도록 어댑터를 장착하기로 결정했다!
PhoneAdapter (Adapter)
PhoneAdapter클래스는 Phone을 구현하고 내부적으로 Tablet을 맴버 변수로 가지고 있다.
기존에 사용하던 Phone인터페이스를 구현하는 것은 같은데 내부적으로는 Tablet의 show()
, exit()
메소드를 호출하게 된다.
이렇게 하면 우리(Client)는 Tablet클래스를 사용할 때 기존에 사용하던 display()
, shutDown()
을 통하여 접근할 수 있게 된다.
정리
어댑터 패턴은 인터페이스 사이에 유연성이 필요한 상황에 효율적으로 사용될 수 있는 디자인 패턴이다.
하지만 코드의 복잡도가 발생할 수 있고 추가적인 오버헤드가 생길 수 있기 때문에 적절한 상황에만 사용하는 것이 좋다.
참고
-
헤드 퍼스트 디자인 패턴