状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态装换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
状态模式优点与应用
状态模式的好处是将与特定状态相关的行为局部化,并且将不同的状态的行为分割开来。就是将特定的状态相关的行为都放入一个对象中,由于所有的与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
说白了,这么做的目的就是为了消除庞大的条件分支语句。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
应用:当一个对象的行为取决于它的状态,并且它必须运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
我是以一天的心情状态为例,写了一个小例子,在写的时候一开始没怎么遇到问题,在最后编译的时候出现了好几个重复的错误,今天把这个错误整理一下,以免下次再犯。
错误:
zhuangtai.cpp:27: 错误:invalid use of incomplete type ‘struct State’ zhuangtai.cpp:5: 错误:forward declaration of ‘struct State’
修改:
这是因为类A和类B内同时使用到了对方,将类A和类B都在之前声明一下,然后将调用对方的函数在类外实现,在两个类都写好后,写这两个函数实现。返回值 类名::函数名(参数列表){函数主体}
#include <iostream> using namespace std; class State; class Forenoon; class Noon; class Afternoon; class Evening; class GoHome; class Work; class State //状态类基类 抽象类 { public: virtual void writeprogram(Work* w) = 0; //当前状态纯虚函数 }; class Work //工作类 { State* current; //当前状态指针 public: double hours; //当前时间 bool finish; //当天任务有没有完成 Work(); //构造函数 初始化当前状态 void SetState(State* s) //设置当前状态 { current = s; } void WorkProgram() //查看当前状态 { current->writeprogram(this); } }; class Forenoon : public State //上午 { public: void writeprogram(Work* w); //当前状态 }; class Noon : public State //中午 { public: void writeprogram(Work* w); //当前状态 }; class Afternoon : public State //下午 { public: void writeprogram(Work* w); //当前状态 }; class Evening : public State //晚上 { public: void writeprogram(Work* w); //当前状态 }; class GoHome : public State //下班回家 { public: void writeprogram(Work* w) //当前状态 { cout<<"当前时间:"<<w->hours<<"点 下班回家"<<endl; } }; Work::Work() //初始化当前状态 { finish = false; current = new Forenoon(); //初始化为上午 } void Forenoon::writeprogram(Work* w) //上午状态函数实现 { if(w->hours < 12) { cout<<"当前时间:"<<w->hours<<"点 上午工作,精神百倍"<<endl; } else //超过12点状态转为中午 { w->SetState(new Noon()); w->WorkProgram(); } } void Noon::writeprogram(Work* w) //中午状态函数实现 { if(w->hours < 13) { cout<<"当前时间:"<<w->hours<<"点 吃午饭,睡午觉"<<endl; } else //超过13点状态转为下午 { w->SetState(new Afternoon()); w->WorkProgram(); } } void Afternoon::writeprogram(Work* w) //下午状态函数实现 { if(w->hours < 17) { cout<<"当前时间:"<<w->hours<<"点 下午状态还不错"<<endl; } else //超过17点状态转为晚上 { w->SetState(new Evening()); w->WorkProgram(); } } void Evening::writeprogram(Work* w) //晚上状态函数实现 { if(w->finish) //任务完成下班 { w->SetState(new GoHome()); w->WorkProgram(); } else //任务未完成 加班 { cout<<"当前时间:"<<w->hours<<"点 加班 好累"<<endl; } } int main() { Work* work = new Work(); work->hours = 10; //设置当前时间 work->WorkProgram(); //查看当前状态 work->hours = 12; //设置当前时间 work->WorkProgram(); //查看当前状态 work->hours = 15; //设置当前时间 work->WorkProgram(); //查看当前状态 work->finish = true; work->hours = 18; //设置当前时间 work->WorkProgram(); //查看当前状态 return 0; } 显示结果:
[hjf@hjf 设计模式]$ ./a.out 当前时间:10点 上午工作,精神百倍 当前时间:12点 吃午饭,睡午觉 当前时间:15点 下午状态还不错 当前时间:18点 下班回家