状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象转换的条件表达式过于复杂时的情况。把状态的判断逻辑移到表示不同状态的一系列当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要用“状态模式”了。
状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,也就是说将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换,说白了就是消除庞大的条件分支条件,大的分支判断会使得他们难以修改和扩展。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少互相依赖。
至于什么时候考虑使用状态模式,当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时。
举个加班例子:
#include <iostream> using namespace std; class Work; class ForenoonState; class NoonState; class AfternoonState; class EveningState; class SleepingState; class RestState; class State { public:virtual void WriteProgram(Work* w)=0; }; class Work { private:State *current;double m_hour;bool m_finish=false; public:Work();void SetState(State *s){this->current=s;}void WriteProgram(){this->current->WriteProgram(this);}void SetHour(double hour){this->m_hour=hour;}double GetHour(){return this->m_hour;}void SetFinish(bool finish){this->m_finish=finish;}bool GetFinish(){return this->m_finish;} }; class RestState:public State {void WriteProgram(Work *w){cout << "当前时间:" << w->GetHour() << "点下班回家了" << endl;} }; class SleepingState:public State { public:void WriteProgram(Work *w){cout << "当前时间:" << w->GetHour() << "点,不行了,睡着了" << endl;} }; class EveningState:public State { public:void WriteProgram(Work *w){if(w->GetHour()<21){cout << "当前时间:" << w->GetHour() << "点,加班哦,疲累之极" << endl;}else{w->SetState(new SleepingState());w->WriteProgram();}} }; class AfternoonState:public State { public:void WriteProgram(Work *w){if(w->GetHour()<17){cout << "当前时间:" << w->GetHour() << "点,下午状态不错,继续努力" << endl;}else{w->SetState(new EveningState());w->WriteProgram();}} }; class NoonState:public State { public:void WriteProgram(Work *w){if(w->GetHour()<13){cout << "当前时间:" << w->GetHour() << "点,饿了,吃饭;犯困午休" << endl;}else{w->SetState(new AfternoonState());w->WriteProgram();}} }; class ForenoonState:public State { public:void WriteProgram(Work *w){if(w->GetHour()<12){cout << "当前时间:" << w->GetHour() << "点,上午工作,精神百倍" << endl;}else{w->SetState(new NoonState());w->WriteProgram();}} }; Work::Work() {current=new ForenoonState(); } int main() {Work *emergencyProjects=new Work();emergencyProjects->SetHour(9);emergencyProjects->WriteProgram();emergencyProjects->SetHour(10);emergencyProjects->WriteProgram();emergencyProjects->SetHour(12);emergencyProjects->WriteProgram();emergencyProjects->SetHour(13);emergencyProjects->WriteProgram();emergencyProjects->SetHour(14);emergencyProjects->WriteProgram();emergencyProjects->SetHour(17);emergencyProjects->WriteProgram();emergencyProjects->SetFinish(true);emergencyProjects->SetHour(19);emergencyProjects->WriteProgram();emergencyProjects->SetHour(22);emergencyProjects->WriteProgram();return 0; }