面向对象设计其实就是希望做到代码责任的分解,类中函数过长意味着它的责任过于大了,一旦需求有任何更改,这个方法可能都需要修改。这违背了单一职责原则,也违背了开放封闭原则。
状态模式:当一个对象的状态改变时允许改变其行为。这对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂是的情况。大部分人的一般做法是使用switch--case或者使用if--else进行处理。这会造成一个问题,分支过多。通过把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
State类,抽象状态类,定义一个接口以封装与Context的一个特定相关状态的行为。
ConcreteState类,具体状态类,每一个类实现与Context的一个特定相关的行为。
Context类,维护一个ConcreteState类的实例,这个实例定义当前的状态。
状态模式的好处:将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。也就是说将特定的状态特定的行为都放入一个对象中,由于所有与状态相关的代码都存在于某一个具体的状态类中,所以通过定义新的子类可以很容易增加新的状态和转换,这样做的目的在于消除条件分支语句,大的分支语句会使他们难以扩展和修改。状态模式通过将各种状态转移逻辑分不到state的子类之间,来减少相互间的依赖。
当一个兑对象的行为取决于它的状态时,就可以考虑使用状态模式了。
State模式同Strategy有很多相似的地方,两者的思想都是一致的,只不过封装的东西不同,State封装的是不同的状态。而strategy封装的不同的算法。
代码结构图:
#include<iostream>
using namespace std;
class State;
class Work
{
public:
State *s;
int hour;
bool isFinished;
public:
Work()
{
hour=0;
isFinished=true;
}
void setState(State *w);
void dosomething();
};
class State
{
public:
State()
{
}
virtual void dosomething(Work*w)=0;
};
class MorniningState:public State
{
public:
MorniningState()
{
}
virtual void dosomething(Work*w);
};
class NoonState:public State
{
public:
NoonState()
{
}
virtual void dosomething(Work*w);
};
class Afternoon:public State
{
public:
Afternoon()
{
}
virtual void dosomething(Work*w);
};
class DuskState:public State
{
public:
DuskState()
{
}
virtual void dosomething(Work*w);
};
class NightState:public State
{
public:
NightState()
{
}
virtual void dosomething(Work*w);
};
void Work::setState(State *w)
{
s=w;
}
void Work::dosomething()
{
s->dosomething(this);
}
void Afternoon::dosomething(Work*w)
{
if(w->hour<15)
cout<<"下午了,该睡午觉没睡,我好困呐!"<<endl;
else
{
w->setState(new DuskState);
w->dosomething();
}
}
void NightState::dosomething(Work*w)
{
if(w->isFinished)
cout<<"下班了,回家陪媳妇去了!!!"<<endl;
else
{
if(w->hour<21)
cout<<"工作没做完,还得加班呐!!!"<<endl;
else
{
cout<<"九点以后还让我干活,没门!!!"<<endl;
}
}
}
void DuskState::dosomething(Work*w)
{
if(w->hour<18)
cout<<"状态终于好起来了!!!"<<endl;
else
{
w->setState(new NightState);
w->dosomething();
}
}
void NoonState::dosomething(Work*w)
{
if(w->hour<13)
cout<<"中午干吃饭了!!!"<<endl;
else
{
w->setState(new Afternoon);
w->dosomething();
}
}
void MorniningState::dosomething(Work*w)
{
if(w->hour<12)
cout<<"上午状态精神不错!!"<<endl;
else
{
w->setState(new NoonState);
w->dosomething();
}
}
int main(int argc,char**argv)
{
Work *w=new Work;
w->setState(new MorniningState);
w->hour=10;
w->dosomething();
w->hour=13;
w->dosomething();
w->hour=16;
w->dosomething();
w->isFinished=false;
w->hour=20;
w->dosomething();
w->hour=22;
w->dosomething();
return 0;
}