[디자인패턴]Adapter2
프로그래밍할 때 늘 백지 상태에서 시작하는 것이 아니다. 이미 존재하는 클래스를 이용하는 경우도 흔하다. 특히 해당 클래스가 충분히 테스트가 되어 버그가 적고 또 실제로 지금까지 사용되어 온 실적이 있다면 더욱 더 그렇다. 어떻게든 그 클래스를 부품으로 재사용하고 싶을 것이다.
Adapter 패턴은 기존 클래스에 한 겹 덧씌워 필요한 클래스를 만든다. 이 패턴을 사용하면 필요한 메소드군을 빠르게 만들 수 있다. 만약 버그가 발생하더라도 기존 클래스(Adaptee 역)에는 버그가 없는 것을 알고 있으므로, Adapter 역의 클래스를 중점적으로 살펴보면 되고 프로그램 검사가 매우 편해진다.
소프트웨어는 버전 업이 필요하다. 소프트웨어를 버전 업할 때는 ‘구버전과의 호환성’이 문제가 된다. 흔히 레거시 시스템(legacy system)으로도 불리는 구버전을 버리면 소프트웨어 유지 보수는 편해지지만, 항상 그럴 수 있는 것은 아니다. Adapter 패턴은 신버전과 구버전을 공존시키고, 유지 보수까지 편하게 하도록 도와준다.
예를 들어 앞으로 신버전만 유지 보수하고 싶을 때는 신버전을 Adaptee 역으로 하고, 구버전을 Target 역으로 한다. 그리고 신버전의 클래스를 사용하여 구버전의 메소드를 구현하는 Adapter 역할 클래스를 만든다.
예제 2
Main 클래스와 Banner 클래스는 앞의 예제 프로그램과 같으면 실행 결과도 동일하다. 하지만 Print 는 인터페이스가 아니고 클래스라고 가정해보자.
즉, Banner 클래스를 이용하여 Print 클래스와 같은 메소드를 갖는 클래스를 실현하려는 것이다. Java에서는 두 개의 클래스를 동시에 상속할 수 없다. 다시 말해, PrintBanner 클래스를 Print와 Banner 양쪽의 하위 클래스로 정의할 수 없다.
PrintBanner 클래스는 banner 필드로 Banner 클래스의 인스턴스를 가진다. 이 인스턴스는 PrintBanner 클래스의 생성자에서 생성한다. printWeak 및 printStrong 메소드에서는 그 banner 필드를 통해 showWithParen, showWithAster 메소드를 호출한다.
PrintBanner 클래스의 printWeak와 printStrong 메소드는 Print 클래스에서 선언된 메소드를 오버라이드하여 구현했으므로, 메소드 앞에 @Override 어노테이션을 사용했다.
자신의 상위 클래스로부터 상속받은 showWithParn, showWithAster 메소드를 호출했지만, banner 필드를 경유해서 호출한다.
여기서 위임이 등장했다. PrintBanner 클래스의 printWeak 메소드가 호출되었을 때 자신이 처리하지 않고, 다른 인스턴스(Banner의 인스턴스)인 showWithParen 메소드에 맡기는 것이다.
1. Print 클래스
public abstract class Print{
public abstract void printWeak();
public abstract void printStrong();
}
2. PrintBanner 클래스
public class PrintBanner extends Print{
private Banner banner;
public PrintBanner(String string){
this.banner = new Banner(string);
}
public void printWeak(){
banner.showWithParen();
}
public void printStrong(){
banner.showWithAster();
}
}
Adapter 역할
-
Client 역 : Target 의 메소드를 사용해 일한다. 예제 프로그램에서는 Main 클래스가 여기에 해당한다.
-
Adaptee(적응 대상자) 역 : Adaopter가 아니라 Adaptee 이다. Adaptee 는 이미 준비되 메소드를 가지는 역할이다. 에제 프로그램에서 Banner 클래스가 이 역할을 맡았다. Adaptee의 메소드가 Target 의 메소드와 일치한다면 Adapter 가 필요 없다.
-
Adapter(적응자) 역 : Adapter 패턴의 주인공이다. Adaptee 의 메소드를 사용해서 어떻게든 Target 을 만족시키는 것이 Adapter 패턴의 목적이며 Adapter 의 임무이다. 교류 100볼트를 직류 12볼트로 변환하는 어댑터에 해당한다. 예제 프로그램에서 PrintBanner 클래스가 이 역할을 수행한다. 클래스에 의한 Adapter 패턴일 때는 Adapter는 ‘상속’하여 Adaptee를 이용한다. 반면에 인스턴스에 의한 Adapter 패턴일 때는 ‘위임’하여 Adaptee를 이용한다.