본문 바로가기
Develop/etc

Adapter Pattern은 무엇인가

by 독서왕뼝아리 2023. 9. 13.

현실 세계의 어댑터를 생각하면 Adapter Pattern을 이해하기 쉽다. USB-A와 USB-C를 연결해야 한다면 불가능하지만 어댑터를 사용하면 가능한 것처럼! 불완전한 서로를 어댑터로 전환시켜 주는 것이다.

 

 

 

이 디자인 패턴에선 어떤 타입을 기대하는 Class(Client)를 가지고 있고, 같은 기능이지만 다른 인터페이스로 노출되어 있

는 객체(Adaptee)를 가지고 있을 때 사용된다.

 

 

그니까! 정리하면

어댑터 패턴은 클래스의 인터페이스를 서버가 기대하는 다른 인터페이스로 변환시켜주는 디자인 패턴이다.

 

 

 

Target 인터페이스(어댑터 아님)를 상속하는 어댑터가 구현되어 있다. 어댑터는 모든 요청을 Adaptee에게 위임한다.

 

 

// Java implementation of Adapter pattern
 
interface Bird
{
    // Bird 인터페이스를 구현체는 fly() 할 수있고
    // 소리를 내는 adaptee 인터페이스를 만들 수 있다
    public void fly();
    public void makeSound();
}
 
class Sparrow implements Bird
{
    // 실제 새 구현체
    public void fly()
    {
        System.out.println("Flying");
    }
    public void makeSound()
    {
        System.out.println("Chirp Chirp");
    }
}
 
interface ToyDuck
{
    // target interface
    // 오리 인형은 날지 못한다
    // 단지 꽥꽥 소리를 낼뿐
    public void squeak();
}
 
class PlasticToyDuck implements ToyDuck
{
    public void squeak()
    {
        System.out.println("Squeak");
    }
}
 
class BirdAdapter implements ToyDuck
{
    // 클라이언트가 사용하고 싶은대로
    // 인터페이스를 구현해야 한다.
    Bird bird;
    public BirdAdapter(Bird bird)
    {
        // 적용하고 싶은 객체의 참조가 필요하다
        this.bird = bird;
    }
 
    public void squeak()
    {
        // translate the methods appropriately
        // 즉시 메소드를 번역한다(?) 
        // squeak() 메소드를 호출하면 곧바로 makeSound()를 호출한다는 뜻?
        bird.makeSound();
    }
}
 
class Main
{
    public static void main(String args[])
    {
        Sparrow sparrow = new Sparrow();
        ToyDuck toyDuck = new PlasticToyDuck();
 
        // Bird 구현체를 BirdAdapter에 주입하면
        // Toy Bird처럼 사용 가능하다!!
        ToyDuck birdAdapter = new BirdAdapter(sparrow);
 
        System.out.println("Sparrow...");
        sparrow.fly();
        sparrow.makeSound();
 
        System.out.println("ToyDuck...");
        toyDuck.squeak();
 
        // 오리 인형은 오리처럼 소리를 낸다
        System.out.println("BirdAdapter...");
        birdAdapter.squeak();
    }
}

 

 

 

 

장점

👍🏻 유연성과 재사용성을 높인다.

👍🏻 다른 인터페이스를 사용하지 않아 클라이언트 클래스가 복잡해지지 않는다.

👍🏻 다양한 어댑터 구현체로 swap할 수 있기 때문에 다형성이 높아짐

 

단점

👎🏻 모든 요청 맨 앞에서 처리되기 때문에 약간의 오버헤드가 증가한다.

👎🏻 가끔 많은 adaptation들은 원하는 타입에 도달하기 위해 adapter chain을 필요로 한다.