퍼사드 패턴 --------------------------------------------------------------------------------------------------
퍼사드 패턴이란 복잡하에 얽혀있는 서브클래스들과 그 클래스가 모여서 이루려는 목적을
클라이언트가 아닌 하나의 클래스에서 종합하는 패턴을 의미한다.
무슨 의미냐. 게임적으로 생각해보면 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(void) const { 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; } |
실행 결과 -------------------------------------------------------------------------------------------------------------------------------
'게임개발공부 > 디자인패턴' 카테고리의 다른 글
구조패턴 <프록시 패턴> (대리자) (0) | 2014.01.05 |
---|---|
구조패턴 <플라이웨이트 패턴> (가벼운 체급) (0) | 2014.01.02 |
구조패턴 <데코레이터 패턴> (표면) (0) | 2013.12.28 |
구조패턴 <컴포지트 패턴> (복합체) (0) | 2013.12.24 |
구조패턴 <브릿지 패턴> (가교) (0) | 2013.12.23 |