...

[JAVA / 디자인 패턴] 어댑터 패턴 ( Adapter Pattern ) 본문

CS/디자인 패턴

[JAVA / 디자인 패턴] 어댑터 패턴 ( Adapter Pattern )

gi2 2021. 11. 17. 23:44

어댑터란 무엇일까?

물리적인 의미로 이야기 하자면, 다른 전기나 기계 장치를 서로 연결해서 작동할 수 있도록 만들어주는 결합 도구이다. 

 

예시로 이야기 하자.

충전 단자 부분이 USB 형식인 애플 충전 케이블이 있을 때, USB 포트 부분을 전원 소켓과 연결할 수 있도록 하는 통로 역할을 해주는 것이 어댑터(Adapter)이다. 

Adapter

 

 

이를 디자인 패턴, 프로그래밍과 연관 시켜 보자. 

기존에 사용하던 A 인터페이스가 있고, 추가적으로 외부에서 들어온 B 인터페이스가 있다. 

이를 연결하려면 인터페이스 2개 중 하나를 대폭 수정하여야 할 것이다.

서로의 형식에 맞추어야 하기 때문이다. 

이런 경우 두 인터페이스 중 어떤 코드도 변경하지 않고 사용 가능하도록 한 것이 어댑터 패턴이다. 

 

 

 

 

어댑터 패턴의 class diagram은 다음과 같다. 

 

 

Target 인터페이스는 원래 소유하고 있던 기존의 인터페이스 A이다. 이를 상속받아 사용하던 기존의 클래스 Client가 있었다. 이 때 인터페이스 B를 상속받아 사용하는 Adaptee 클래스가 사용되어야 한다. 따라서 Adapter라는 연결 포트를 설정한다. Adapter는 기본적으로 본래의 인터페이스 A의 형식을 따른다. 인터페이스A 형식 안에서 Adaptee 클래스의 기능들을 구현함으로써 이 둘을 연결할 수 있게 된다. 

 

오리를 관리하는 인터페이스 안에서, 오리 대신 칠면조를 추가로 들여오려 한다. 기존의 오리 인터페이스는 유지하면서 칠면조를 편하게 관리하기 위해서는 (디자인 패턴 원칙 - 수정에는 닫혀있어야 한다.) 오리 인터페이스와 칠면조 인터페이스를 연결해주는 어댑터가 필요하다. 

 

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

기존 인터페이스 A (= 오리를 관리하는 인터페이스 = Target 인터페이스) 가 있다. 

 

public class Mallarduck implements Duck{

    @Override
    public void quak() {
        System.out.println("Quack");
    }

    @Override
    public void fly() {
        System.out.println("I'm flying");
    }
}

 그리고 인터페이스 A를 상속받아 이용하는 Client, Mallacduck 클래스가 있다. 

 

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

 

새로 추가해야 하는 칠면조 인터페이스(인터페이스 B)이다. 

 

public class WildTurkey implements Turkey {
    @Override
    public void gobble() {
        System.out.println("Gobble gobble");
    }

    @Override
    public void fly() {
        System.out.println("I'm flying short distance");
    }
}

칠면조 인터페이스를 상속받는 WildTurkey 클래스이다.

오리와는 우는 방식도, 나는 방식도 다르다. 이 부분을 해결해야 한다. 

 

public class TurkeyAdapter implements Duck {
    Turkey turkey;

    public TurkeyAdapter(Turkey turkey)
    {
        this.turkey= turkey;
    }

    @Override
    public void quak() {
        turkey.gobble();
    }

    @Override
    public void fly() {
        for(int i=0;i<5;i++)
            turkey.fly();
    }
}

따라서 터키 어댑터가 필요하다. 어댑터는 기존 인터페이스 A인 오리 인터페이스를 상속받고, 추가적으로 터키 객체를 받아온다. 오리 인터페이스의 틀 안에서 칠면조의 기능들을 수행하도록 구현함으로써 표면적으로는 오리를 다루듯 칠면조를 다룰 수 있는 것이다. 

 

public class DuckTestDrive {
    public static void main(String[] args) {
        WildTurkey turkey = new WildTurkey();
        Duck TurkeyAdapter = new TurkeyAdapter(turkey);

        System.out.println("The TurkeyAdapter says...");
        TurkeyAdapter.fly();
        TurkeyAdapter.quak();
    }
}

Main 클래스에서는 칠면조 객체를 생성한 후 Duck 객체인 TurkeyAdapter를 호출한다.

그리고 Duck 객체 TurkeyAdapter에서 turkey를 받아옴으로써 두 인터페이스를 연결할 수 있게 된다. 

Comments