객체지향 프로그래밍은 클래스를 통해서 만들어진 객체들의 기능을 통해서 만들어 진다.
이때 객체들의 기능은 클래스 단계에서 정적으로 고정된 경우가 많다.
데코레이터 패턴이란 이러한 기존에 구성된 정적인 객체의 기능을 동적으로 할당하고 삭제하는데 그 의미가 있다.
이러한 경우는 일반적으로 캐릭터의 모션이 완전히 바뀌어야 하거나 혹은 전혀 다른 패시브 스킬들을 적용시켜야 할때 필요하다.
즉 내부의 조건문을 통한 기능의 변화가 아닌 객체 자체를 동적으로 기능변경 시켜 코드량을 줄이고 새로운 패턴을 추가하는 것이다.
패턴적용 스토리 -----------------------------------------------------------------------------------------------
당신은 액션 게임을 만들고 있습니다. 모든 플레이어는 기본공격을 가지는데 당신은 그에 대한 디자인을 맡았습니다.
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; } |
'게임개발공부 > 디자인패턴' 카테고리의 다른 글
구조패턴 <플라이웨이트 패턴> (가벼운 체급) (0) | 2014.01.02 |
---|---|
구조패턴 <퍼사드 패턴> (표면, 정면) (0) | 2013.12.28 |
구조패턴 <컴포지트 패턴> (복합체) (0) | 2013.12.24 |
구조패턴 <브릿지 패턴> (가교) (0) | 2013.12.23 |
uml 관계도 좀더 명확히 (1) | 2013.12.22 |