본문 바로가기
프로그래밍/디자인패턴

Adapter Pattern

by 리뷰하는 (게임)프로그래머_리프TV 2016. 6. 7.

Adapter Pattern에 대해사 알아 보도록 하겠습니다.

 

해당 패턴을 알아 보기전에 한가지 문제점에 대해서 먼저 알고 넘어가야 합니다.

 

[상황]

1. [인사]를 출력하는 클래스가 존재

 

[추가 할 내용]

1. [닉네임]을 추가로 출력 필요

2. [닉네임]을 먼저 출력 하거나, 인사를 먼저 출력 할 수 있음

 

물론 [인사]를 출력하는 부분에서 [닉네임]을 받아서 함께 처리 하여도 됩니다.

 

하지만, 

 

기존의 코드를 수정하고 싶지 않을 경우, 또는 하지 못하는 경우에 다음과 같은 방법을 사용합니다.

 

먼저 해당 부분은 2가지 방법이 존재하는데 

 

interface 를 사용하는 상속으로만 해결 하는 방법과,

상속, 위임(포함)을 통한 방법이 있습니다.

 

물론 2가지 모두 Adapter Pattern 입니다.

 

코드를 확인하도록 하겠습니다. 

 

namespace AdapterPatternEx1
{
    // "안녕하세요."를 출력하는 클래스가 있습니다.
    // 이 클래스를 AdapterPattern을 사용해 확장해 보도록 합시다.
    public class HelloPrint
    {
        private string hello;
        public HelloPrint()
        {
            hello = "안녕하세요.";
        }

        public void SayHello()
        {
            Debug.Log(hello);
        }
    }

    // 먼저 interface를 활용한 방법입니다.
    public interface StringPrint
    {
        void firstHello();
        void lastHello();
    }

    // 기존에 Hello Print와 새로운 interface인 StringPrint를 모두 상속받습니다.
    public class NamePrint : HelloPrint, StringPrint
    {
        string namePrint;
        public NamePrint(string name)
        {
            namePrint = name;
        }
        public void lastHello()
        {
            Debug.Log(namePrint + ", ");
            // 부모 클래스로써 상속받은 함수를 호출합니다.
            SayHello();
        }

        public void firstHello()
        {
            // 부모 클래스로써 상속받은 함수를 호출합니다.
            SayHello();
            Debug.Log(namePrint);
        }
    }

    // 실제로 사용하는 예제
    public class AdapterClass : MonoBehaviour
    {
        // interface 를 생성 합니다.
        StringPrint namePrint = new NamePrint("캡틴후크");

        void Start()
        {
            // 원하는 기능을 출력합니다.
            Debug.Log("firstHello call");
            namePrint.firstHello();
            Debug.Log("lastHello call");
            namePrint.lastHello();
        }
    }
}​

StringPrint라는 interface를 추가로 제작해서 기존의 기능을 두면서 원하는 기능을 추가하였습니다.

 

현재 단계에서는 interface를 사용하든 확장된 클래스를 사용 하던 큰 차이는 없으나,

사용자에게 좀더 명확함을 주기 위해서 interface를 사용하는 것을 추천합니다.

 

그리고 두번째 방법으로 

상속, 위임을 통한 방법에 대해서 알아 보도록 하겠습니다. 

 

namespace AdapterPatternEx2
{
    // 역시나 "안녕하세요."를 출력하는 class가 존재합니다.
    public class HelloPrint
    {
        private string hello;
        public HelloPrint()
        {
            hello = "안녕하세요.";
        }

        public void SayHello()
        {
            Debug.Log(hello);
        }
    }

    // 이번엔 가상 한수를 만들어 접근해 보도록 합시다.
    public abstract class StringPrint
    {
        public abstract void lastHello();
        public abstract void firstHello();
    }

    // StringPrint를 상속 받고
    public class NamePrint : StringPrint
    {
        // 기존의 클래스를 포함하여 진행합니다.
        HelloPrint helloPrint = new HelloPrint();

        string namePrint;
        public NamePrint(string name)
        {
            namePrint = name;
        }
        public override void lastHello()
        {
            Debug.Log(namePrint);
            // 결과는 기존과 동일 하나, 이번엔 다음처럼 지정하여 사용합니다.
            helloPrint.SayHello();
        }

        public override void firstHello()
        {
            // 결과는 기존과 동일 하나, 이번엔 다음처럼 지정하여 사용합니다.
            helloPrint.SayHello();
            Debug.Log(namePrint);
        }
    }

    public class AdapterClass : MonoBehaviour
    {
        // StringPrint class로 하든 namePrint로 하던 현재로썬 큰 의미가 없습니다.
        StringPrint namePrint = new NamePrint("캡틴후크");

        void Start()
        {
            Debug.Log("firstHello call");
            namePrint.firstHello();
            Debug.Log("lastHello call");
            namePrint.lastHello();
        }
    }
}​

이렇게 Adapter Pattern을 사용해서 문제를 해결하는 방법에 대해서 알아 보았습니다. 

 

Adapter Pattern에 대해서 정의를 내리면 책에서는 다음과 같이 이야기 합니다. 

 

- Wrapper(감싸는) Pattern 이라고도 함 

- 이미 작동 하고 있는 ( 문제가 없는, 충분히 테스트된 ) 코드를 수정하지 않고, 개조하기 위해서 사용.

- 구 버전과의 호환성을 제공 할 수 있음.

 

마지막으로 용어 적인 부분과 다이어 그램을 확인 하고 Adapter Pattern은 마무리 짓도록 하겠습니다.

 

용어적인 부분

- Target( 예제 코드의 Interface [StringPrint]나, 가상 클래스인 [StringPrint] class )

- Client( Main 실행 코드, 예제 코드의 [AdapterClass] class )

- Adaptee( 예제 코드의 [HelloPrint] class  )

- Adapter( 예제 코드의 [NamePrint] class )

 

다이어그램으로 표현

인터페이스를 사용한 Adapter Pattern

 

위임(포함)을 사용한 Adapter Pattern

 

 

다음은 Template Method Pattern 에 대해서 알아 보도록 하겠습니다.

 

'프로그래밍 > 디자인패턴' 카테고리의 다른 글

Factory Mathod Pattern  (0) 2017.04.12
Template Method Pattern  (0) 2016.06.30
Iterator Pattern  (0) 2016.05.04
UML의 기본 구성-시퀀스 다이어그램  (4) 2016.05.02
UML의 기본 구성-클래스 다이어그램  (0) 2016.05.02