데코레이터 패턴 --------------------------------------------------------------------------------------------------

  객체지향 프로그래밍은 클래스를 통해서 만들어진 객체들의 기능을 통해서 만들어 진다.

  이때 객체들의 기능은 클래스 단계에서 정적으로 고정된 경우가 많다.

  데코레이터 패턴이란 이러한 기존에 구성된 정적인 객체의 기능을 동적으로 할당하고 삭제하는데 그 의미가 있다.

  이러한 경우는 일반적으로 캐릭터의 모션이 완전히 바뀌어야 하거나 혹은 전혀 다른 패시브 스킬들을 적용시켜야 할때 필요하다.

  즉 내부의 조건문을 통한 기능의 변화가 아닌 객체 자체를 동적으로 기능변경 시켜 코드량을 줄이고 새로운 패턴을 추가하는 것이다.


패턴적용 스토리 -----------------------------------------------------------------------------------------------

  당신은 액션 게임을 만들고 있습니다. 모든 플레이어는 기본공격을 가지는데 당신은 그에 대한 디자인을 맡았습니다.

  1모션 -> 2 모션 -> 3모션 을 사용하면 다음 모션을 사용하고 다음 모션을 사용하는 식입니다.

  모든 플레이어는 3개의 모션을 가지며 당신은 그 모션과 특성들을 잘 디자인하라는 명령을 받았습니다.

  회사에서 원하는 조건은 다음과 같습니다.


  1. 플레이어는 최대 3연속 연속기를 사용한다.

  2. 이 모션들은 세팅에 따라서 언제든지 변할 수 있다.

  3. 최대 3개의 모션이기는 하지만 하나의 모션만 가질수도 2개의 모션만 가질수도 있게 디자인해야 한다.

  4. 기본 동작은 전투 준비 모션이다.


  제가 감안해야할 사항은 다음과 같았습니다.

  1. 만약 플레이어에게 3개의 공격동작이 있다면 언제든지 중간과정에서 추가가 가능해야한다.

  2. 기존에 모션이 세팅되어 있다고 하더라도 그 모션을 언제든지 교체할수 있어야 한다.


uml -----------------------------------------------------------------------------------------------



만약 최대 3개의 모션이 아니라 몇개든 추가될수 있다고 한다면 모션을 STL로 관리할 수도 있을 것이다.



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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#pragma once
 
#include "include.h"
 
enum MOTIONQUEUE
{
    MOTIONQUEUE_1,
    MOTIONQUEUE_2,
    MOTIONQUEUE_3,
};
 
enum PLAYERMOTION
{
    PLAYERMOTION_NONE,
    PLAYERMOTION_UPSWING,
    PLAYERMOTION_DOWNSWING,
    PLAYERMOTION_SIDESWING,
    PLAYERMOTION_PIERCE,
};
 
class WeaponMotion
{
public:
    virtual void AttMotion(void) = 0;
    virtual void SetMotion(WeaponMotion* _PlayerMotion) = 0;
 
public:
    WeaponMotion(void) {}
    virtual ~WeaponMotion(void) {}
};
 
class DecoratorMotion
    : public WeaponMotion
{
private:
    WeaponMotion* m_PlayerMotion;
 
public:
    virtual void AttMotion(void)
    {
        if(m_PlayerMotion != NULL)
            m_PlayerMotion->AttMotion();
    }
 
    virtual void SetMotion(WeaponMotion* _PlayerMotion)
    {
        m_PlayerMotion = _PlayerMotion;
    }
 
public:
    DecoratorMotion(void) : m_PlayerMotion(NULL) {}
    DecoratorMotion(WeaponMotion* _PlayerMotion) : m_PlayerMotion(NULL) { m_PlayerMotion = _PlayerMotion; }
    virtual ~DecoratorMotion(void) {}
};
 
class FightReady
    : public DecoratorMotion
{
public:
    void AttMotion(void)
    {
        cout << "전투준비!" << endl;
        DecoratorMotion::AttMotion();
    }
 
    void SetMotion(WeaponMotion* _PlayerMotion)
    { DecoratorMotion::SetMotion(_PlayerMotion); }
 
public:
    FightReady(void) {}
    FightReady(WeaponMotion* _PlayerMotion) : DecoratorMotion(_PlayerMotion) { }
    virtual ~FightReady(void) {}
};
 
class UpSwing
    : public DecoratorMotion
{
public:
    void AttMotion(void)
    {
        cout << "위로 올려벤다" << endl;
        DecoratorMotion::AttMotion();
    }
 
    void SetMotion(WeaponMotion* _PlayerMotion)
    { DecoratorMotion::SetMotion(_PlayerMotion); }
 
public:
    UpSwing(void) {}
    UpSwing(WeaponMotion* _PlayerMotion) : DecoratorMotion(_PlayerMotion) { }
    virtual ~UpSwing(void) {}
};
 
class DownSwing
    : public DecoratorMotion
{
public:
    void AttMotion(void)
    {
        cout << "아래로 내려친다" << endl;
        DecoratorMotion::AttMotion();
    }
 
    void SetMotion(WeaponMotion* _PlayerMotion)
    { DecoratorMotion::SetMotion(_PlayerMotion); }
 
public:
    DownSwing(void){}
    DownSwing(WeaponMotion* _PlayerMotion) : DecoratorMotion(_PlayerMotion) { }
    virtual ~DownSwing(void){}
};
 
class SideSwing
    : public DecoratorMotion
{
public:
    void AttMotion(void)
    {
        cout << "측면으로 베어낸다" << endl;
        DecoratorMotion::AttMotion();
    }
 
    void SetMotion(WeaponMotion* _PlayerMotion)
    { DecoratorMotion::SetMotion(_PlayerMotion); }
 
public:
    SideSwing(void) {}
    SideSwing(WeaponMotion* _PlayerMotion) : DecoratorMotion(_PlayerMotion) { }
    virtual ~SideSwing(void) {}
};
 
class Pierce
    : public DecoratorMotion
{
public:
    void AttMotion(void)
    {
        cout << "찌른다!" << endl;
        DecoratorMotion::AttMotion();
    }
 
    void SetMotion(WeaponMotion* _PlayerMotion)
    { DecoratorMotion::SetMotion(_PlayerMotion); }
 
public:
    Pierce(void) {}
    Pierce(WeaponMotion* _PlayerMotion) : DecoratorMotion(_PlayerMotion) { }
    virtual ~Pierce(void) {}
};
 
class CPlayer
{
private:
    WeaponMotion*        MotionReady;
    WeaponMotion*        Motion1;
    WeaponMotion*        Motion2;
    WeaponMotion*        Motion3;
 
public:
    void SetMotion(const PLAYERMOTION& _AttMotionType, const MOTIONQUEUE& MotionNum)
    {
        switch(MotionNum)
        {
        case MOTIONQUEUE_1:
            CreMotion(_AttMotionType, &Motion1);
            if(MotionReady != NULL)
            { MotionReady->SetMotion(Motion1); }
            else
            { MotionReady->SetMotion(NULL); }
            break;
        case MOTIONQUEUE_2:
            CreMotion(_AttMotionType, &Motion2);
            if(Motion1 != NULL)
            { Motion1->SetMotion(Motion2); }
            else
            { MotionReady->SetMotion(NULL); }
            break;
        case MOTIONQUEUE_3:
            CreMotion(_AttMotionType, &Motion3);
            if(Motion2 != NULL)
            { Motion2->SetMotion(Motion3); }
            else
            { MotionReady->SetMotion(NULL); }
            break;
        }
    }
 
    void CreMotion(const PLAYERMOTION& _AttMotionType, WeaponMotion** _PlayerMotion)
    {
 
        SAFE_DELETE(*_PlayerMotion);
 
        switch(_AttMotionType)
        {
        case PLAYERMOTION_NONE:
            break;
        case PLAYERMOTION_UPSWING:
            *_PlayerMotion = new UpSwing();
            break;
        case PLAYERMOTION_DOWNSWING:
            *_PlayerMotion = new DownSwing();
            break;
        case PLAYERMOTION_SIDESWING:
            *_PlayerMotion = new SideSwing();
            break;
        case PLAYERMOTION_PIERCE:
            *_PlayerMotion = new Pierce();
            break;
        }
    }
 
    void Attact(void)
    {
        MotionReady->AttMotion();
        cout << endl;
    }
 
public:
    CPlayer(void)
    : MotionReady(NULL)
    , Motion1(NULL)
    , Motion2(NULL)
    , Motion3(NULL)
    {
        MotionReady = new FightReady();
        MotionReady->SetMotion(NULL);
    }
    ~CPlayer(void
    {
        SAFE_DELETE(MotionReady);
        SAFE_DELETE(Motion1);
        SAFE_DELETE(Motion2);
        SAFE_DELETE(Motion3);
    }
};
 
int _tmain(int argc, _TCHAR* argv[])
{
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
    //_CrtSetBreakAlloc(219);
#endif
 
    CPlayer* Player = new CPlayer();
 
    Player->SetMotion(PLAYERMOTION_UPSWING, MOTIONQUEUE_1);
    Player->SetMotion(PLAYERMOTION_PIERCE, MOTIONQUEUE_2);
 
    Player->Attact();
 
    Player->SetMotion(PLAYERMOTION_PIERCE, MOTIONQUEUE_1);
    Player->SetMotion(PLAYERMOTION_SIDESWING, MOTIONQUEUE_2);
    Player->SetMotion(PLAYERMOTION_PIERCE, MOTIONQUEUE_3);
 
    Player->Attact();
 
    Player->SetMotion(PLAYERMOTION_NONE, MOTIONQUEUE_1);
    Player->SetMotion(PLAYERMOTION_NONE, MOTIONQUEUE_2);
    Player->SetMotion(PLAYERMOTION_NONE, MOTIONQUEUE_3);
 
    Player->Attact();
 
    SAFE_DELETE(Player);
 
    return 0;
}
 
 




Posted by JJOREG