状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
将与特点状态相关的行为局部化,并且将不同状态的行为分割开来!
UML:
代码实现:
以前很喜欢玩war3里面的国家对抗,是一个建造类游戏。里面的建筑在不同的时候有不同的状态,例如兵营在产兵的时候会发白光,
受伤的时候会着火,建造的时候有建筑特效。兵营在建造没完成的时候不能升级和产兵,升级的时候不能产兵,受伤着火了也能继续产兵或升级。
假设这些建筑的状态和表现为:建造-建造特效、受伤-受伤着火、升级-升级蓝光、生成-生产白光、修复-修复绿光。
实现各种状态代码state.h:
1 #ifndef STATE_H 2 #define STATE_H 3 #include <iostream> 4 using namespace std; 5 6 class absState{ 7 public: 8 virtual void show() = 0; 9 }; 10 11 class buildingState:public absState{ 12 public: 13 virtual void show() 14 { 15 cout<<"建造特效 "; 16 } 17 }; 18 19 class fireState:public absState{ 20 public: 21 virtual void show() 22 { 23 cout<<"受伤着火 "; 24 } 25 }; 26 27 class productionState:public absState{ 28 public: 29 virtual void show() 30 { 31 cout<<"生产白光 "; 32 } 33 }; 34 35 class upGradeState:public absState 36 { 37 public: 38 virtual void show() 39 { 40 cout<<"升级蓝光 "; 41 } 42 }; 43 44 class repairState:public absState 45 { 46 public: 47 virtual void show() 48 { 49 cout<<"修复绿光 "; 50 } 51 }; 52 #endif
建筑实现代码building.h:
1 #ifndef BUILDING_H 2 #define BUILDING_H 3 #include "state.h" 4 5 #include <map> 6 #include <iostream> 7 using namespace std; 8 9 enum StateType 10 { 11 BUILDING, INJURED, REPAIR, UPGRADE, PRODUCTION 12 }; 13 14 class absBuilding 15 { 16 public: 17 absBuilding(char* name):mName(name){} 18 virtual void show() 19 { 20 cout<<mName<<"表现:"<<endl; 21 map<StateType, absState*>::iterator beg = mStates.begin(); 22 for ( ; beg != mStates.end(); beg++) 23 { 24 beg->second->show(); 25 } 26 cout<<endl; 27 }; 28 void eraseState(StateType type) //实现删除一个特效 29 { 30 auto result = mStates.find(type); 31 if(result != mStates.end()) 32 mStates.erase(result); 33 } 34 protected: 35 char* mName; 36 map<StateType, absState*> mStates; 37 }; 38 39 class concreteBuilding:public absBuilding 40 { 41 public: 42 concreteBuilding(char* name):absBuilding(name) 43 { 44 mStates[BUILDING] = new buildingState(); 45 } 46 void upGrade() 47 { 48 auto result = mStates.find(UPGRADE); 49 if(result == mStates.end()) 50 { 51 mStates[UPGRADE] = new upGradeState(); 52 } 53 eraseState(BUILDING); //升级的时候必须是建造过程已经结束,所以需要删掉“建筑”状态 54 eraseState(PRODUCTION); //升级的时候不能进行生产 55 } 56 void production() 57 { 58 auto result = mStates.find(PRODUCTION); 59 if(result == mStates.end()) 60 { 61 mStates[PRODUCTION] = new upGradeState(); 62 } 63 eraseState(BUILDING); //生产的时候必须已经建造完成 64 eraseState(UPGRADE); //生产的时候不能升级 65 } 66 void injured() 67 { 68 auto result = mStates.find(INJURED); 69 if(result == mStates.end()) 70 { 71 mStates[INJURED] = new fireState(); 72 }74 } 75 void repair() 76 { 77 auto injuredVal = mStates.find(INJURED); 78 if(injuredVal == mStates.end()) 79 return; 80 auto result = mStates.find(REPAIR); 81 if(result == mStates.end()) 82 { 83 mStates[REPAIR] = new repairState(); 84 }86 } 87 }; 88 89 #endif
客户端代码main.cpp:
1 #include <iostream> 2 #include "tank.h" 3 #include "building.h" 4 5 using namespace std; 6 class SiegeTank; 7 8 void main() 9 { 10 concreteBuilding cb("兵营"); 11 cb.production(); 12 cb.injured(); 13 cb.repair(); 14 cb.show(); 15 return; 16 }
结果: