Adapter Pattern

개념
- 이미 제공하는것과 필요한것 과의 사이의 간격을 메우는 패턴

I. 의도

     클래스 인터페이스를 클라이언트가 기대하는 형태의 인터페이스로 변환. 호환성이 없는 인터페이스때문에 함께 사용할 수 없는 클래스를 개조하여 함께 작동하도록 해 준다(기존에 이미 존재하나 새롭게 만들어서 적용할 클래스와 같이 작동하도록 해야 함)

  정의 : 이미 제공하는것과 필요한것 과의 사이의 간격을 메우는 패턴.
     ※ 클래스에 의한 Adapter패턴(상속을 이용한 것) – 클래스 어댑터
     ※ 인스턴스에 의한 Adapter패턴 (위임을 이용한것) – 객체 어댑터 ç 연관관계에 의해

 

          : 객체를 감싸서 다른 인터페이스를 제공 한다.

              ※Adapter는 Target 인터페이스를 구현하고 Adaptee클래스를 상속받는다

          Adapter메서드는 상속받은 Adaptee의 메서드로 위임 시킨다.

II. 활용

  • 기존 클래스를 사용해야 하나 인터페이스가 수정되어야 하는 경우
  • 이미 만들어진 것을 재사용하고자 하나 이 재사용 가능한 라이브러리를 수정할 수 없는 경우
  • 이미 존재하는 여러 개의 서브클래스를 사용해야 할 때, 서브클래스 상속을 통해 인터페이스를 모두 변경하는 것이 현실적으로 어렵다면 객체 어댑터 방식으로 부모 클래스의 인터페이스를 변형하는 것이 바람직

III. 고려사항

  • adapter 클래스가 실제를 개조를 위해 수행해야 하는 일의 정도
  • 대체할 수 있는(pluggable) 어댑터 사용 – 재사용성 높이기 위해
  • 양방향 어댑터 사용 –개조되는 두 클래스 모두의 인터페이스를 다 상속받아 정의하는 것

IV. 결과

  • 클래스 어댑터 – 한 adapter 객체만 만들어 내고 adaptee에 대한 어떠한 참조자도 필요하지 않음.

Adaptee에 정의된 행위 재정의 가능

  • 객체 어댑터 – 어댑터 클래스가 하나만 존재해도 많은 adaptee 클래스와 동작 가능.

Adaptee에 정의된 행위 재정의 어려움

관련 패턴: Bridge 패턴은 객체 Adapter패턴과 클래스 구조가 유사하나 사용 목적이 다르다. Bridge 패턴은 구현과 추상 개념을 분리해 서로에게 영향을 주지 않고 각각을 확장할 수 있도록 하는 것이나, Adapter 패턴은 존재하는 객체의 인터페이스를 변경하려는 것이다

Decorator 패턴은 다른 인터페이스의 변경없이도 객체에 새로운 행위를 추가할 수 있도록 한다. 이것이 adapter보다는 애플리케이션을 위한 훨씬 좋은 방법이고, 순수한 어댑터로는 불가능한 재귀적 합성을 가능하게 한다

Proxy 패턴은 다른 객체에 대한 대표자 또는 대리인의 역할을 수행하지만 인터페이스를 변경하는 책임은 없다

 

1) 다중상속을 이용한 Adapter패턴

 

2) 객체합성에 의한 Adapter패턴

 

구분

설명

예시

Client 역할

어떠한 행위가 필요한 객체

직류 12볼트로 움직이는 노트북

Target 역할

Client에게 필요한 메소드를 제공

노트북 작동에 필요한 직류 12볼트

Adaptee 역할

이미 준비되어 있는 메소드를 가지고 있음

교류 100봍트의 AC전원

Adapter 역할

Adaptee의 메소드를 활용해서 Target이 필요로 하는 메소드를 만들어냄

교류 100볼트를 직류 12볼트로 바꾸어 주는 어뎁터

 

소스코드

1) 클래스에 의한 Adapter 패턴 (상속)

1) 1) Print 인터페이스 구현 (Target 역할)

public interface Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

2) Banner 클래스 구현 (Adaptee 역할)

public class Banner {
    private String string;
    public Banner(String string) {
        this.string = string;
    }
    public void showWithParen() {
        System.out.println("(" + string + ")");
    }
    public void showWithAster() {
        System.out.println("*" + string + "*");
    }
}

3) PrintBanner 구현 (Adapter 역할)

public class PrintBanner extends Banner implements Print {
    public PrintBanner(String string) {
        super(string);
    }
    public void printWeak() {
        showWithParen();
    }
    public void printStrong() {
        showWithAster();
    }
}

(a)  어뎁터의 역할을 완수합니다.

(b) 준비된 Banner 클래스를 확장(extends)해서 showWithParen 메소드와 showWithAster 메소드를 상속합니다.

(c) 또한 필요한 Print 인터페이스를 구현(implement)해서 PrintWeak 메소드와 PrintStrong 메소드를 구현합니다.

 

2) 인스턴스에 의한 Adapter 패턴 (위임)

1) Print 인터페이스 구현 (Target 역할)

public interface Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

2) Banner 클래스 구현 (Adaptee 역할)

public class Banner {
    private String string;
    public Banner(String string) {
        this.string = string;
    }
    public void showWithParen() {
        System.out.println("(" + string + ")");
    }
    public void showWithAster() {
        System.out.println("*" + string + "*");
    }
}

3) PrintBanner 구현 (Adapter 역할)

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();
    }
}

 

 

댓글