장식자( Decorator )

Posted 2012. 10. 23. 15:34

클래스 기능의 동적인 추가를 가능하게 하는 구조 !!

클래스의 기능이 추가된 확장 클래스 객체 생성을 런타임에 동적으로 할 수 있게 하는 패턴

장식적인 의미의 추가 기능들과 오리지널 클래스를 분리하여 합성 객체에 대한 융통성을 제공함.

하지만 장식이 될 객체의 최상위 부모 클래스는 작고 가벼워야 효율적이다. 왜냐면

장식이 중복된 규모있는 클래스를 객체화 할 경우 부모의 크기에 따라 객체의 크기가 커지고

기능적으로 장식자에 부담으로 작용 되기 때문.

중간 클래스로 Decorator를 두는 것이 좋다. 두지 않으면 최상위 클래스가 Deco객체도 관리하게 

되므로 Deco객체만의 Interface를 가질 수 없게 된다.

Decorator클래스는 구현될 일이 없으므로 abstract class로 둔다.


사용 예)

게임 플레이 도중 새로운 아이템을 추가 시키거나 삭제 시킬때.

오락실 비행기 게임, 아이템 먹을수록 미사일 파워 증가.

처럼 다른객체에 영향을 주지 않고 객체에 기능을 추가하고 싶을때

상속을 통한 기능확장이 어려울때.


단점.

( 장식자 개수 * 부모 클래스 크기 ) 만큼 객체 하나의 부담이 증가한다.

장식자나 오리지널 객체 자체가 가벼워져서 그 의미가 뚜렷하지 않으면 그 수가 많아질경우

관리가 힘들어진다.


전략(Strategy) 패턴과의 비교.

객체의 내부가 아닌 외부적인 기능의 추가에 적합것이 장식자 패턴

배주 자체에 기능의 변경이라던지 추가에는 전략 패턴이 적합.

전략 패턴은 직접 오리지널과 같은 부모를 상속받는 것이고 따로 기능만 정의해서 오리지널을 참조를 통해 접근 하는 패턴.



#include <iostream>

using namespace std;


// 최상위 순수 가상. 작고 가벼워야 효율적

//인간클래스

class Human

{

public:

virtual ~Human(){};

public:

virtual void Draw() = 0;

};


// 여자 클래스

class Girl : public Human

{

public:

virtual void Draw()

{    

cout << "여자 출력" << endl;

}

};


// 장식 클래스

class Decorator : public Human

{

protected:

Human *ori;

public:

Decorator( Human *ori )

{

this->ori = ori;

}

virtual ~Decorator()

{

delete ori;

}

public:

virtual void Draw()

{

ori->Draw();

}

};


// 귀걸이 ㅡㄹ래스

class Earring : public Decorator

{

public:

Earring( Human *ori ) : Decorator( ori )

{

}

virtual void Draw()

{

Decorator::Draw();

cout << "귀걸이 출력" << endl;

}

};


// 안경 클래스

class Glass : public Decorator

{

public:

Glass( Human *ori ) : Decorator( ori )

{

}

virtual void Draw()

{

Decorator::Draw();

cout << "안경 출력" << endl;

}

};


void main()

{

cout << "---안경 여자 ---" << endl;

Human *girl = new Girl;

Human *GlassGirl = new Glass( girl );    // 안경 여자

GlassGirl->Draw();


cout << endl;


cout << "---안경 귀걸이 여자---" << endl;

Human *girl2 = new Girl;

Human *GlassEarringGirl = new Glass( new Earring( girl2) );    // 안경 귀걸이 여자

GlassEarringGirl->Draw();


delete GlassGirl;

delete GlassEarringGirl;

}

-> --- 안경 여자 ---

-> 여자 출력

-> 안경 출력

-> --- 안경 귀걸이 여자 ---

-> 여자 출력

-> 귀걸이 출력

-> 안경 출력