在面向对象的思想下,经常会遇到这种这种情况,同一个对象在不同 状态下的表现是不一样的。
比如 一个人情绪的低落和高昂,甚至吃了兴奋剂,他竞技时跑步的速度肯定是不一样的。
同样你的空调 包含 制冷、制热、送风、除湿 等多个模式,每种模式下其属性都不同。
看明白了吗?这就是 状态模式,状态模式 允许一个对象在其内部状态改变的时候改变其行为。
环境(Context):定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态;
抽象状态(State):定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为;
具体状态(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。
// Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
class Context
{
public:
Context(State state)
{
this->nowState = state;
}
// 对请求做处理,并设置下一个状态
void Request()
{
nowState.Handle(this);
}
protected:
State nowState;
};
// 抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
class StateBase
{
virtual void Handle(Context context);
}
// 具体状态类,每一个子类实现一个与Context的一个状态相关的行为
class ConcreteStateA : public StateBase
{
// 设置ConcreteStateA的下一个状态是ConcreteStateB
virtual void Handle(Context context)
{
cout<<"当前状态 A"<<endl;
context.nowState = ConcreteStateB();
}
};
class ConcreteStateB : public StateBase
{
// 设置ConcreteStateB的下一个状态是ConcreteSateA
virtual void Handle(Context context)
{
cout<<"当前状态 B"<<endl;
context.nowState = ConcreteStateA();
}
};
调用代码示例:
// 调用代码
void main(char* args)
{
// 设置Context的初始状态为ConcreteStateA
Context context( ConcreteStateA() );
// 进行请求,同时更改状态
context.Request();
context.Request();
}
状态模式 主要解决的是 当一个对象状态转换的条件表达式过于复杂的情况。通过把状态的判断逻辑转移到一系列类当中,把复杂的逻辑判断简单化。
状态模式 带来的问题就是 需要针对每个状态对象生成一个具体类,因此,状态数量不能过多,当你设计的状态模式类超过5个的时候,你就要考虑 这种模式是否适合了?