状态模式(State),当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类【DP】
状态模式主要解决的是,当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
当然如果这个状态判断很简单,那就没有必要用‘状态模式’了。
我的实现源代码:
state.h
1 #ifndef STATE_H 2 #define STATE_H 3 4 class Context; 5 //my code 6 class State 7 { 8 public: 9 virtual void Handle(Context *pContext) = 0; 10 }; 11 12 class Context 13 { 14 public: 15 Context(State *pState); 16 ~Context(); 17 void Request(); 18 void SetState(State *pState); 19 20 private: 21 State *m_State; 22 }; 23 24 class ConcreteA : public State 25 { 26 public: 27 virtual void Handle(Context *pContext); 28 }; 29 30 class ConcreteB : public State 31 { 32 public: 33 virtual void Handle(Context *pContext); 34 }; 35 36 #endif // STATE_H
state.cpp:
1 #include "state.h" 2 #include <iostream> 3 4 using namespace std; 5 6 Context::Context(State *pState) 7 { 8 this->m_State = pState; 9 } 10 11 Context::~Context() 12 { 13 14 } 15 16 void Context::SetState(State *pState) 17 { 18 if(pState != NULL) 19 this->m_State = pState; 20 } 21 22 void Context::Request() 23 { 24 this->m_State->Handle(this); 25 } 26 27 void ConcreteA::Handle(Context *pContext) 28 { 29 cout<<"this is concrete A"<<endl; 30 pContext->SetState(new ConcreteB()); 31 } 32 33 void ConcreteB::Handle(Context *pContext) 34 { 35 cout<<"this is concrete B"<<endl; 36 pContext->SetState(new ConcreteA()); 37 }
main.cpp
#include <iostream> #include "state.h" using namespace std; int main() { State *pState = new ConcreteA(); Context *c = new Context(pState); c->Request(); c->Request(); c->Request(); c->Request(); return 0; }
状态模式好处与用处
“状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来【DP】。”
“将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换【DP】。”
主要的目的是:消除庞大的条件分支语句,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,好比把整个版面改成一个又一个的活字,此时就容易维护和扩展了。
当一个对象的行为取决与它的状态,并且他必须在运行时刻根据状态改变它的行为时,就可以考虑状态模式了。
工作状态-状态模式版(c++)
workstate.h
1 #ifndef WORKSTATE_H 2 #define WORKSTATE_H 3 4 class Work; 5 6 class WorkState 7 { 8 public: 9 virtual void WriteProgram(Work *pWork) = 0; 10 WorkState(); 11 }; 12 13 class Work 14 { 15 public: 16 Work(WorkState *pWorkState); 17 void ChangeWorkState(WorkState *pWorkState); 18 int GetWorkHour(); 19 void ChangeWorkHour(int hour); 20 void ChangeWorkFinishFlag(bool flag); 21 bool GetWorkFinishFlag(); 22 void Writing(); 23 24 private: 25 WorkState *m_WorkState; 26 int m_Hour; 27 bool m_Finishflag; 28 }; 29 30 class WorkMorning : public WorkState 31 { 32 public: 33 virtual void WriteProgram(Work *pWork); 34 }; 35 36 class WorkNoon : public WorkState 37 { 38 public: 39 virtual void WriteProgram(Work *pWork); 40 }; 41 42 class WorkAfternoon : public WorkState 43 { 44 public: 45 virtual void WriteProgram(Work *pWork); 46 }; 47 48 class WorkNight : public WorkState 49 { 50 public: 51 virtual void WriteProgram(Work *pWork); 52 }; 53 54 class WorkOff : public WorkState 55 { 56 public: 57 virtual void WriteProgram(Work *pWork); 58 }; 59 60 class WorkSleep : public WorkState 61 { 62 public: 63 virtual void WriteProgram(Work *pWork); 64 }; 65 66 #endif // WORKSTATE_H
workstate.cpp
1 #include "workstate.h" 2 #include <iostream> 3 4 using namespace std; 5 6 WorkState::WorkState() 7 { 8 9 } 10 11 Work::Work(WorkState *pWorkState) 12 { 13 this->m_WorkState = pWorkState; 14 this->m_Hour = 0; 15 this->m_Finishflag = false; 16 } 17 18 void Work::ChangeWorkState(WorkState *pWorkState) 19 { 20 this->m_WorkState = pWorkState; 21 } 22 23 int Work::GetWorkHour() 24 { 25 return m_Hour; 26 } 27 28 void Work::ChangeWorkHour(int hour) 29 { 30 this->m_Hour = hour; 31 } 32 33 void Work::ChangeWorkFinishFlag(bool flag) 34 { 35 this->m_Finishflag = flag; 36 } 37 38 bool Work::GetWorkFinishFlag() 39 { 40 return m_Finishflag; 41 } 42 43 void Work::Writing() 44 { 45 this->m_WorkState->WriteProgram(this); 46 } 47 48 void WorkMorning::WriteProgram(Work *pWork) 49 { 50 if(pWork->GetWorkHour() < 12) 51 cout<<"WorkMorning: Work very good."<<endl; 52 else{ 53 // cout<<"WorkMorning: change to Noon"<<endl; 54 pWork->ChangeWorkState(new WorkNoon()); 55 pWork->Writing(); //切换后运行 56 } 57 } 58 59 void WorkNoon::WriteProgram(Work *pWork) 60 { 61 if(pWork->GetWorkHour() < 13) 62 cout<<"WorkNoon: hungry, lunch: sleeping"<<endl; 63 else { 64 pWork->ChangeWorkState(new WorkAfternoon()); 65 pWork->Writing(); 66 } 67 } 68 69 void WorkAfternoon::WriteProgram(Work *pWork) 70 { 71 if(pWork->GetWorkHour() < 17) 72 cout<<"WorkAfternoon: Work very good"<<endl; 73 else { 74 pWork->ChangeWorkState(new WorkNight()); 75 pWork->Writing(); 76 } 77 } 78 79 void WorkNight::WriteProgram(Work *pWork) 80 { 81 if(pWork->GetWorkFinishFlag()) { 82 pWork->ChangeWorkState(new WorkOff()); 83 pWork->Writing(); 84 } 85 else { 86 if(pWork->GetWorkHour() < 21) 87 cout<<"WorkNight: Work very tired"<<endl; 88 else { 89 pWork->ChangeWorkState(new WorkSleep()); 90 pWork->Writing(); 91 } 92 } 93 } 94 95 void WorkOff::WriteProgram(Work *pWork) 96 { 97 cout<<"WorkOff: happy"<<endl; 98 } 99 100 void WorkSleep::WriteProgram(Work *pWork) 101 { 102 cout<<"WorkSleep: Can't Work"<<endl; 103 }
main.cpp
1 #include <iostream> 2 #include "workstate.h" 3 4 using namespace std; 5 6 int main() 7 { 8 WorkState *pState = new WorkMorning(); 9 Work *pWork = new Work(pState); 10 11 pWork->ChangeWorkHour(9); 12 pWork->Writing(); 13 pWork->ChangeWorkHour(10); 14 pWork->Writing(); 15 pWork->ChangeWorkHour(12); 16 pWork->Writing(); 17 pWork->ChangeWorkHour(13); 18 pWork->Writing(); 19 pWork->ChangeWorkHour(14); 20 pWork->Writing(); 21 pWork->ChangeWorkHour(17); 22 23 pWork->ChangeWorkFinishFlag(false); 24 // pWork->ChangeWorkFinishFlag(true); 25 pWork->Writing(); 26 27 pWork->ChangeWorkHour(19); 28 pWork->Writing(); 29 pWork->ChangeWorkHour(22); 30 pWork->Writing(); 31 32 return 0; 33 }