Thinking Different






Composite Pattern - 컴포지트 패턴


  • 객체와 객체의 그룹을 구분없이 하나의 인터페이스로 다룰 수 있게 한다.
  • 객체(Leaf)와 구성(Composite)을 트리로 구성하여 하나의 인터페이스에서 사용하도록 고려한 패턴이다.







샘플 코드)

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
#include <list>
 
//------------------------------------------------------------------
// Component 인터페이스
class Component
{
public:
    virtual void operation() = 0;
    virtual void add(Component* c) {}
    virtual void remove(Component* c) {}
    virtual Component* getChild(int i) { return 0; }
};
 
//------------------------------------------------------------------
// Leaf 상속 클래스
class Leaf : public Component
{
public:
    void operation() override { cout << "Leaf operation" << endl; }
};
 
//------------------------------------------------------------------
// Composite 상속 클래스 (객체 관리)
class Composite : public Component
{
public:
    void operation() override 
    {
        for (auto it = mList.begin(); it != mList.end(); it++)
        {
            (*it)->operation();
        }
    }
    void add(Component* c) override { mList.push_back(c); }
    void remove(Component* c) override { mList.remove(c); }
    Component* getChild(int i) override 
    {
        int ii = 0;
        for (auto it = mList.begin(); it != mList.end(); it++, ii++)
        {
            if (i == ii)
                return *it;
        }
 
        return NULL;
    }
 
private:
    list<Component*> mList;
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    Leaf LeafA;
    Leaf LeafB;
    Composite mComposite;
 
    mComposite.add(&LeafA);
    mComposite.add(&LeafB);
 
    mComposite.operation();
 
    return 0;
}




예제를 통한 컴포지트 패턴(Composite Pattern) 알아보기


예제) 유닛들을 통합 관리하는 예제 (스타크래프트의 유닛 그룹 지정)



다음과 같이 3가지의 유닛 클래스를 정의하고, 부대지정 클래스에서 유닛에 대해서 통합 관리한다.



예제 코드)

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <atlcoll.h>
 
//------------------------------------------------------------------
// IUnit 인터페이스
class 유닛
{
public:
    virtual void 공격() = 0;
    virtual void 이동() = 0;
    virtual void 추가(유닛* c) {}
    virtual void 삭제(유닛* c) {}
    virtual 유닛* 얻기(int i) { return 0; }
};
 
//------------------------------------------------------------------
// 마린 상속 클래스
class 마린 : public 유닛
{
public:
    void 공격() override { cout << "마린 공격" << endl; }
    void 이동() override { cout << "마린 이동" << endl; }
};
 
//------------------------------------------------------------------
// 파이어벳 상속 클래스
class 파이어벳 : public 유닛
{
public:
    void 공격() override { cout << "파이어벳 공격" << endl; }
    void 이동() override { cout << "파이어벳 이동" << endl; }
};
 
//------------------------------------------------------------------
// 시즈탱크 상속 클래스
class 시즈탱크 : public 유닛
{
public:
    void 공격() override { cout << "시즈탱크 공격" << endl; }
    void 이동() override { cout << "시즈탱크 이동" << endl; }
};
 
//------------------------------------------------------------------
// Composite 상속 클래스 (객체 관리)
class 부대지정 : public 유닛
{
public:
    void 공격() override
    {
        POSITION pos = mList.GetHeadPosition();
        while (pos != NULL)
        {
            mList.GetNext(pos)->공격();
        }
    }
 
    void 이동() override
    {
        POSITION pos = mList.GetHeadPosition();
        while (pos != NULL)
        {
            mList.GetNext(pos)->이동();
        }
    }
 
    void 추가(유닛* c) override { mList.AddTail(c); }
    void 삭제(유닛* c) override { mList.RemoveAt(mList.Find(c)); }
    유닛* 얻기(int i) override
    {
        int iCount = 0;
 
        POSITION pos = mList.GetHeadPosition();
        while (pos != NULL)
        {
            if ( iCount++ == i )
                return mList.GetNext(pos);
        }
 
        return NULL;
    }
 
private:
    CAtlList<유닛*> mList;
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
    마린 mMarin;
    파이어벳 mFirebet;
    시즈탱크 mSiegeTank;
 
    부대지정 mComposite;
 
    mComposite.추가(&mMarin);
    mComposite.추가(&mFirebet);
    mComposite.추가(&mSiegeTank);
 
    mComposite.공격();
    mComposite.이동();
 
    return 0;
}


예제코드에서는 CAtlList 를 사용하였습니다. CAtlList에 대한 자세한 내용은 CAtlList 사용법 및 정리 를 참고하세요


예제 결과)