퍼사드 패턴 --------------------------------------------------------------------------------------------------

  퍼사드 패턴이란 복잡하에 얽혀있는 서브클래스들과 그 클래스가 모여서 이루려는 목적을

  클라이언트가 아닌 하나의 클래스에서 종합하는 패턴을 의미한다.

  무슨 의미냐. 게임적으로 생각해보면 MMORPG게임에서 경매장이라는 기능을 보자.

  이 경매장 클래스 내부에서 모든 기능을 가질수는 없기 때문에(혹은 경매장에서 사용하는 기능을 다른 기능에서 사용할수 있으니)

  클래스나 서브시스템으로 분리되어 있을 것입니다.


1. 검색 기능(클래스 또는 함수)

2. 플레이어 금액정산 기능(클래스 또는 함수)

3. 상품발송 기능(클래스 또는 함수)

4. 거래량 판단기능(클래스 또는 함수)

5. 경매장 랜더 기능(클래스 또는 함수)


  위의 기능들이 클래스 안에 들어있다고 생각해봅시다. 클라이언트에서 경매장의 온전한 기능을 사용하려면 저 기능들을 잘 조합해서 사용해야 할 것입니다.

  퍼사드 패턴은 이러한 기능들을 하나의 클래스 안에 묶어서 외부에서 그 하나의 클래스를 통해서 저 기능들을 종합하여 사용하게 하는 패턴을 의미합니다.


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

  당신은 턴제게임의 행동패턴을 맡게 되었습니다.

  당신에게 요구된 사항과 제공되는 서브시스템들은 다음과 같습니다.

  1. 캐릭터 클래스

  2. 캐릭터의 수만큼 캐릭터에게 행동력을 부여하는 기능

  3. 부여된 행동력만큼 캐릭터들을 정렬시켜주는 기능(행동력이 높은 순서대로, 행동력이 같다면 캐릭터 인덱스가 낮은 순서대로 행동한다)

  4. 정렬된 캐릭터의 액션을 동작시키는 기능


  이 기능들을 조합하여 각 캐릭터의 행동을 하게 만들어야 합니다.


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




포면 알겠지만 액션퍼사드 클래스는 각 클래스와 기능들을 내부에서 종합하게 되어 외부에서 캐릭터를 캐릭터를 정렬하고 캐릭터가 행동하게 하는 기능은 모두 액션퍼사드 클래스를 가지게 됩니다. 즉 외부로 드러나는 인터페이스와 기능을 하나의 외부 인터페이스에 모아 놓는 패턴입니다.


코드 -------------------------------------------------------------------------------------------------------------------


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
#pragma once
 
#include "include.h"
 
enum CHARACTER_ACTION
{
    CHARACTER_ACTION_RELAX,
    CHARACTER_ACTION_ATT,
    CHARACTER_ACTION_DEF,
    CHARACTER_ACTION_MOVE,
    CHARACTER_ACTION_COUNT,
};
 
typedef struct _tagCharacterInfo
{
    int CharacterIndex;
    int ActionPoint;
    int ActionType;
    int Speed;
    int Move;
    int Att;
    int Def;
    int Relax;
 
    void Setting( const _tagCharacterInfo& _CharacterInfo ) { *this = _CharacterInfo; }
 
    _tagCharacterInfo(void)  { }
    _tagCharacterInfo(int _CharacterIndex, int _ActionPoint, int _ActionType, int _Speed,  int _Move, int _Att, int _Def, int _Relax)
        : CharacterIndex(_CharacterIndex), ActionPoint(_ActionPoint), ActionType(_ActionType), Speed(_Speed)
        , Move(_Move), Att(_Att), Def(_Def), Relax(_Relax) { }
    _tagCharacterInfo( const _tagCharacterInfo& _CharacterInfo ) { *this = _CharacterInfo; }
 
}CHARACTERINFO, *PCHARACTERINFO;
 
class CCharacter
{
private:
    CHARACTERINFO    m_CharacterInfo;
 
public// Get
    const CHARACTERINFO& GetCharacterInfo(voidconst 
    { return m_CharacterInfo; }
 
public// Set
    void SetUserInput(const int& _CharacterAct)
    { m_CharacterInfo.ActionType = _CharacterAct; }
    void SetActionPoint(const int& _ActionPotin)
    { m_CharacterInfo.ActionPoint = _ActionPotin; }
 
public:
    void Action(void)
    {
        switch(m_CharacterInfo.ActionType)
        {
        case CHARACTER_ACTION_RELAX :
            Relax();
            break
        case CHARACTER_ACTION_ATT :
            Att();
            break
        case CHARACTER_ACTION_DEF :
            Def();
            break
        case CHARACTER_ACTION_MOVE :
            Move(); 
            break
        }
    }
 
    void ActionPointRender(void
    {
        cout << "행동력" << m_CharacterInfo.ActionPoint << "**********" <<endl;
    }
 
    void Relax(void
    {    
        ActionPointRender();
        cout << m_CharacterInfo.CharacterIndex << "번 캐릭터는 휴식한다" << endl; 
        cout << m_CharacterInfo.Relax << "만큼 회복했다!" << endl; 
    }
    void Att(void
    {    
        ActionPointRender();
        cout << m_CharacterInfo.CharacterIndex << "번 캐릭터는 공격한다" << endl; 
        cout << m_CharacterInfo.Att << "만큼 공격했다!" << endl; 
    }
    void Def(void
    {    
        ActionPointRender();
        cout << m_CharacterInfo.CharacterIndex << "번 캐릭터는 방어한다" << endl; 
        cout << m_CharacterInfo.Def << "만큼 방어했다!" << endl; 
    }
    void Move(void
    {    
        ActionPointRender();
        cout << m_CharacterInfo.CharacterIndex << "번 캐릭터는 이동한다" << endl; 
        cout << m_CharacterInfo.Move << "만큼 이동했다!" << endl; 
    }
 
public:
    CCharacter(void) {}
    CCharacter(const CHARACTERINFO& _CharacterInfo) { m_CharacterInfo = _CharacterInfo; }
    ~CCharacter(void) {}
};
 
class CUserInputQueue
{
private:
    queue<int> UserInput;
 
public:
    void SetUserInput(const int& _MaxCharacter)
    {
        for(int i = 0 ; i < _MaxCharacter ; ++i)
        {
            UserInput.push(rand() % CHARACTER_ACTION_COUNT);
        }
    }
 
    void SetUserInputToCharacter(CCharacter* const _Character)
    {
        _Character->SetUserInput(UserInput.front());
        UserInput.pop();
    }
 
 
public:
    CUserInputQueue(void) {}
    ~CUserInputQueue(void) {}
};
 
class CCharacterSort
{
private:
    map<int, map<int, CCharacter*>> m_mapCharacter;
 
public:
    void PushCharacter(CCharacter* const _Character)
    {
        map<int, map<int, CCharacter*>>::iterator FirIter = m_mapCharacter.find(_Character->GetCharacterInfo().ActionPoint);
 
        if(FirIter == m_mapCharacter.end())
        {
            map<int, CCharacter*> _TempMap;
 
            _TempMap.insert(map<int, CCharacter*>::value_type(_Character->GetCharacterInfo().CharacterIndex, _Character));
 
            m_mapCharacter.insert(map<int, map<int, CCharacter*>>::value_type(
                _Character->GetCharacterInfo().ActionPoint
                ,_TempMap));
        }
        else
        {
            FirIter->second.insert(map<int, CCharacter*>::value_type(_Character->GetCharacterInfo().CharacterIndex, _Character));
        }
    }
 
    void ActionPlayer(void)
    {
        if(!m_mapCharacter.empty())
        {
            map<int, map<int, CCharacter*>>::reverse_iterator reFirIter;
 
            map<int, CCharacter*>::iterator SecIter;
 
            for(reFirIter = m_mapCharacter.rbegin() ; reFirIter != m_mapCharacter.rend() ; ++reFirIter)
            {
                for( SecIter = reFirIter->second.begin() ; SecIter != reFirIter->second.end() ; ++SecIter)
                {
                    SecIter->second->Action();
                }
            }
        }
    }
 
public:
    CCharacterSort(void) {}
    ~CCharacterSort(void) {}
};
 
class CActionFacade
{
private:
    list<CCharacter*> m_CharacterList;
 
public:
    void PushPlayer(CCharacter* const _Character)
    { 
        m_CharacterList.push_back(_Character); 
    }
 
    void Action(void)
    {
        CUserInputQueue _InputQueue;
        _InputQueue.SetUserInput(m_CharacterList.size());
 
        CCharacterSort _CharacterSort;
 
        for(list<CCharacter*>::iterator Iter = m_CharacterList.begin(); Iter != m_CharacterList.end() ; ++Iter)
        {
            (*Iter)->SetActionPoint(rand() % (*Iter)->GetCharacterInfo().Speed);
            _InputQueue.SetUserInputToCharacter(*Iter);
            _CharacterSort.PushCharacter(*Iter);
        }
 
        _CharacterSort.ActionPlayer();
    }
 
    void Release(void)
    {
        if(!m_CharacterList.empty())
        {
            for(list<CCharacter*>::iterator Iter = m_CharacterList.begin(); Iter != m_CharacterList.end() ; ++Iter)
            {
                SAFE_DELETE(*Iter);
            }
            m_CharacterList.clear();
        }
    }
 
 
public:
    CActionFacade(void) {}
    ~CActionFacade(void) {}
};
 
// facade.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include "Facade.h"
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    CActionFacade Facade;
 
    for(int i = 0 ; i < 5 ; ++i)
    { Facade.PushPlayer(new CCharacter(CHARACTERINFO(i,0,0,rand() % 100 + 1,0,0,0,0))); }
 
    Facade.Action();
 
    Facade.Release();
 
    return 0;
}
 
 


실행 결과 -------------------------------------------------------------------------------------------------------------------------------



Posted by JJOREG