본문 바로가기

: Desgin Pattern

Adapter Pattern

반응형

Adapter Pattern (== Wrapper)

 

용어

  • Target: 사용하려는 클래스나 오브젝트
  • Client: Target 을 사용하려는 주체이다. Targert Interface 를 사용한다.
  • Adpater: Target을 적합한 폼으로 바꿔준다. Adaptee interface 를 사용한다.
  • Adaptee: Adapter에 의해서 변경되는 클래스나 오브젝트

 

패턴의 목적

 

UML

서로 다른 인터페이스가 함께 동작할 수 있게 만드는 것.

어댑터

현실의 어댑터와 비슷하다.
즉, 내가 사용하려는 인터페이스에 맞게 바꿔주는 것이 목적이다. 유사하지만 다른 두 개의 클래스에 접근하려고 할 때, 어댑터를 통해서, 변경없이 하나처럼 사용할 수 있도록 하는 것이다.
어댑터 패턴은 재사용성을 높여준다.

 

 

쉬운 이해를 위해 아래 예제를 살펴보자.

public interface Duck {
    public void quack();
    public void fly();
}

public class MallardDuck implements Duck {
    public void quack() {
        System.out.println("Quack!");
    }
    public void fly() {
        System.out.println("I am flying!");
    }
}

public interface Turkey {
    public void gobble();
    public void fly();
}

public class wildTurkey implements Turkey {
    public void gobble(){
        System.out.println("Gobble Gobble");
    }
    public void fly(){
        System.out.println("I am flying a short distance.");
    }
}

Duck 은 Target 이며, Turkey는 Adaptee 이다.
즉, 오리를 사용하는 Client 는 터키도 오리처럼 사용하려 한다.
하지만 Turkey와 Duck 은 가지고 있는 함수도 다르며, 같은 interface도 공유하지 않는다.
Adapter 를 구현하여 Turkey가 Duck의 방식으로 동작하게 하는 것이 목적이다.

 

Duck interface를 따르는 TurkeyAdapter를 만들어보자.

public class TurkeyAdapter implements Duck {
    Turkey turkey;
    
    public TurkeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }
    
    public void quack() {
        turkey.gobble();
    }
    
    public void fly() {
        for(int i = 0; i < 5; ++i) {
            turkey.fly();
        }
    }
}

quack을 호출하면, turkey.gobble() 이 1회 호출되고, fly()를 호출하면, 터키.fly()를 5번 호출하도록 구성되어 있다.

요악하면, Adaptee 에 Adapter Pattern 을 적용하여 Target 처럼 동작하게 하는 것이 목적이다.
해당 예시는 Object Adapter 방식이다.
(참고로, 자바에서는 다중 상속을 지원하지 않으므로, Class Adapter는 구현이 불가능하다.)

 

 

Object Adapter vs Class Adapter

 

Adapter라는 것은 뭔지 대충 알았을 거라 생각한다.
근데 갑자기 또 새로운 개념인 Object Adapter랑 Class Adapter라는 말을 하니 또 무슨 말인가 싶을 수있다.
아래에서 알아보도록 하자.

둘 다 공통적으로, Target 을 Implements 한다는 공통점을 갖고있다.
차이점은 object로 갖고 있냐, class로 갖고있냐의 차이이다.
Target은 똑같이 implements 하므로 생략하고 살펴보자.

 

Object Adapter

위의 예시는 Target을 제외한 Object Adapter 간략한 구조이다. 
위를 살펴보면 변수로 adaptee: Adaptee로 갖고 있는 것을 알 수 있다.
즉, Adaptee를 Object로 갖고 있어서 Object Mapper인 것이다.
adaptee 처럼 동작하기 위해, Adapter에서 methodA()가 호출되면 adaptee.methodB(); 가 동작하도록 한다.

예시로 코드로 살펴보면,

class Adapter implements Target {
    Adaptee adaptee;
    
    void methodA() {
        // ...
        adaptee.methodB();
        // ...
    }
}

와 같이 되어있는 구조이다.

한마디로 요약하면, Target을 implements하고, adaptee를 object로 가진 Adapter 이다. 

 

 

Class Adapter

위의 예시는 Target을 제외한 Class Adapter 이다.
위의 그림을 보면 Adapter는  Adaptee1 ... N을 모두 상속을 받는다.
즉, class Adapter는 부모로 Adaptee1, Adaptee2 ... AdapteeN을 모두 상속받아야 한다는 의미이다. 그러기 위해 다중상속이 가능해야만 한다.

그러나 아쉽게도 자바는 지원하지 않으므로, Adaptee가 하나인 경우만 자바 코드로 예시로 쓸 수 있겠다.

코드로 살펴보면,

class Adapter extends Adaptee1 implements Target {
    
    void methodA() {
        // ...
        methodB(); // it is called from Adaptee.methodB();
        // ...
    }
}

와 같이 되어있는 구조이다.

한마디로 요약하면, Target을 implements하고, adaptee class를 상속받은 Adapter 이다. 

 

ref)
https://en.wikipedia.org/wiki/Adapter_pattern

반응형

': Desgin Pattern' 카테고리의 다른 글

MVC  (0) 2021.08.19
Composite Pattern  (0) 2021.07.25
Design Pattern  (0) 2021.07.05