728x90

기존에 사용하던 모듈에서 새로운 라이브러리로 교체를 해야 할 때 만약 새로운 모델의 인터페이스가 다르면 호출하는 부분을 모두 따라가서 호출 부분을 수정해야 할 것입니다. 이럴 경우 모든 부분에 대한 수정이 어려울 뿐 아니라 많은 비용이 들 수 있습니다. 아니면 라이브러리를 수정하는 방법이 있는데 소스코드가 제공이 안되면 수정이 불가능하고 제공한다고 해도 해석하고 수정하는데도 많은 시간과 비용이 필요합니다.

 

PowerPoint에서 기존에 상단 메뉴에서 오브젝트를 끌고와 화면에 그려주는 기능이 있다고 합시다. 그 오브젝트들은 현재 원, 사각형, 삼각형 등이 구현되어있습니다. 근데 여기서 텍스트 상자 오브젝트를 추가로 구현하려고 했는데 이미 라이브러리가 있어서 갖다 사용하려 합니다. 하지만 기존의 오브젝트들은 Object로부터 상속받아 추상화되어 인터페이스가 동일하지만 텍스트 상자는 그렇지 않습니다.

간단히 사용할 수 있는 방법은 오브젝트를 화면에 그릴때 오브젝트에 따라 구분해서 그려주는 방법이 있습니다.

class Object { virtual void Draw() = 0; };

class Circle : public Object {
	void Draw() { cout << "Draw Circle"; }
};

class TextBox {
	void ViewText() { cout << "View Text"; }
};

void DisplayObject(Object* pObj, TextBox* pTBox)
{
    if (pObj != 0) { pObj.Draw(); }
    else if (pTBox != 0) { pTBox.ViewText(); }
}

int main()
{
    TextBox tBox;
    DisplayObject(0, &box);
}

이렇게 사용한다면 구분은 할 수 있지만 해당 오브젝트를 사용하는 부분마다 모두 저 함수를 사용해야 하기 때문에 번거로울 수 있습니다. 

 

이런 번거로움을 방지하기 위한 제일 좋은 방법은 자료형을 통해 구분하지 않게 자료형을 통일시켜주는 방법입니다. TextBox를 새로 Object를 상속받는 TextBoxObject로 정의하고 Draw() 인터페이스를 가지게 하면 됩니다. 해당 방법도 두 가지 방법으로 구현할 수 있는데 TextBoxObject에서 Draw()가 호출되면 TextBox의 ViewText를 호출하는 방법입니다.

class Object { virtual void Draw() = 0; };

class Circle : public Object {
    void Draw() { cout << "Draw Circle"; }
};

class TextObject : public Object {
    TextObject() { pObj = new TextBox; }
    void Draw() { pObj->ViewText(); }
private:
    TextBox* pObj;
};

class TextBox {
    void ViewText() { cout << "View Text"; }
};

void DisplayObject(Object* pObj)
{
    if (pObj != 0) { pObj.Draw(); }
}

int main()
{
    TextObject tBox;
    DisplayObject(&box);
}

두 번째는 TextObject를 Object도 상속받고 TextBox도 상속받게 하는 방법입니다. 이 경우 TextBox 클래스는 private로 상속받아 구현하는 방법입니다. 이렇게 되면 public으로 상속받은 Object의 자료형으로 사용할 수 있으면서 TextBox의 ViewText함수도 사용할 수 있습니다. 만약 ViewText도 public으로 상속하면 자료형을 Object로도 ViewText로도 사용할 수 있지만 두 자료형의 병행 사용으로 인해 혼란을 초래할 수 있습니다.

class Object { virtual void Draw() = 0; };

class Circle : public Object {
    void Draw() { cout << "Draw Circle"; }
};

class TextObject : public Object, private Textbox {
    void Draw() { ViewText(); }
};

class TextBox {
    void ViewText() { cout << "View Text"; }
};

void DisplayObject(Object* pObj)
{
    if (pObj != 0) { pObj.Draw(); }
}

int main()
{
    TextObejct tBox;
    DisplayObject(&box);
}

첫 번째 Adapter를 Object Adapter 패턴이라 하고 두 번째 Adapber를 Class Adapter 패턴이라 합니다. 두 패턴의 차이는 원래의 클래스를 새로운 클래스에서 객체를 생성해서 사용하느냐 혹은 상속해서 사용하느냐의 차이입니다.

 

이처럼 어댑터 패턴을 사용하면 기존 클래스를 재사용함에 있어 인터페이스가 맞지 않을 때 그에 맞춰 사용할 수 있습니다. 

728x90

'Programming > C++' 카테고리의 다른 글

C++ 컴포지트 패턴  (0) 2021.05.15
C++ 브릿지 패턴  (0) 2021.05.15
C++ 싱글톤 패턴  (0) 2021.05.09
C++ 프로토 타입 패턴  (0) 2021.05.08
C++ 팩토리 메소드 패턴  (0) 2021.05.08

+ Recent posts