Thinking Different






Decorator Pattern - 데코레이터 패턴


  • 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴으로, 기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 유연한 대안이 될 수 있다. (위키디피아 데코레이터 패턴 정의)
  • 동적으로 객체의 추가적인 기능들을 가진 객체를 덧붙여 꾸밀 수 있다.






샘플 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//------------------------------------------------------------------
// Component 인터페이스
class Component
{
public:
    virtual void operation() = 0;
};
 
//------------------------------------------------------------------
// ConcreteComponent 상속 클래스
class ConcreteComponent : public Component
{
public:
    void operation() { cout << "ConcreteComponent" << endl; }
};
 
//------------------------------------------------------------------
// Decorator 상속 클래스
class Decorator : public Component
{
public:
    Decorator(Component* c) : pComponent(c) {}
    ~Decorator() { if (pComponent) delete pComponent; }
 
public:
    void operation() { if (pComponent) pComponent->operation(); }
 
private:
    Component* pComponent;
};
 
//------------------------------------------------------------------
// ConcreteDecorator 상속 클래스
class ConcreteDecorator : public Decorator
{
public:
    ConcreteDecorator(Component* d) : Decorator(d) {}
 
public:
    void operation() { Decorator::operation(); cout << "ConcreteDecorator" << endl; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    Component* pComponent = new ConcreteDecorator(new ConcreteDecorator(new ConcreteComponent()));
    pComponent->operation();
    delete pComponent;
 
    return 0;
}




예제를 통한 데코레이터 패턴(Decorator Pattern) 알아보기


예제) 커피 주문 예제


커피 인터페이스를 기준으로 일반 커피와 커피 데코레이터가 존재하고, 커피 데코레이터는 밀크와 휘핑크림을 두었다. 

커피에 데코레이션 패턴으로 우유나 휘핑크림을 추가할 수 있는 구조이고, 각각의 비용과 재료들은 사용될 때마다 추가 합산되도록 처리되었다.


예제 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <locale>
 
#if _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
 
//------------------------------------------------------------------
// Component 인터페이스
class ICoffeeComponent
{
public:
    virtual int GetCost() = 0;
    virtual tstring GetIngredients() = 0;
};
 
//------------------------------------------------------------------
// ConcreteComponent 상속 클래스
class Coffee : public ICoffeeComponent
{
public:
    int GetCost() { return 1000; }
    tstring GetIngredients() { return _T("커피"); }
};
 
//------------------------------------------------------------------
// Decorator 상속 클래스
class CoffeeDecorator : public ICoffeeComponent
{
public:
    CoffeeDecorator(ICoffeeComponent* c) : pComponent(c) {}
    ~CoffeeDecorator() { if (pComponent) delete pComponent; }
 
public:
    int GetCost() { if (pComponent) return pComponent->GetCost(); else return 0; }
    tstring GetIngredients() { if (pComponent) return pComponent->GetIngredients(); else return _T(""); }
 
private:
    ICoffeeComponent* pComponent;
};
 
//------------------------------------------------------------------
// ConcreteDecorator 상속 클래스
class MilkDecorator : public CoffeeDecorator
{
public:
    MilkDecorator(ICoffeeComponent* d) : CoffeeDecorator(d) {}
 
public:
    int GetCost() { return CoffeeDecorator::GetCost() + 200; }
    tstring GetIngredients() { return _T("우유 + ") + CoffeeDecorator::GetIngredients(); }
};
 
class WhipCreamDecorator : public CoffeeDecorator
{
public:
    WhipCreamDecorator(ICoffeeComponent* d) : CoffeeDecorator(d) {}
 
public:
    int GetCost() { return CoffeeDecorator::GetCost() + 500; }
    tstring GetIngredients() { return _T("휘핑크림 + ") + CoffeeDecorator::GetIngredients(); }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    _wsetlocale(LC_ALL, L"korean");
 
    ICoffeeComponent* pComponent = new MilkDecorator(new WhipCreamDecorator(new CoffeeDecorator(new Coffee())));
    wcout << _T("비용 : ") << pComponent->GetCost() << endl;
    wcout << _T("재료 : ") << pComponent->GetIngredients().c_str() << endl;
    delete pComponent;
 
    getchar();
 
    return 0;
}


예제 결과