状态模式:电梯想要移动首先得是关门的。
定义:当一个对象内在状态改变时,允许其改变行为,这个对象看起来像改变了其类。
翻译:就是没有某个状态,就不能做出某行为。因为类的动作一般是在任何情况下都可以调用的,受到状态的限制后,就像是基于不同的状态而换了不同的类一样,对着状态机理解就可。
类图摘自设计模式之禅:
state抽象状态角色,接口或抽象类:
负责对象状态定义,封装环境角色以实现状态切换。
封装对象的所有功能函数,已满足实现不同的状态。
concretestate具体状态角色,两个职责:
本状态的行为管理,就是本状态下要干的事。
趋向状态处理,就是本状态过渡到其他状态的条件。
context环境角色:
定义客户端需要的接口,负责具体状态的切换。
其实就是物体对象本身或指针啦,物体通过转换状态适应需求,而适应需求就是物品指针委托状态类完成的。
环境角色的不成文约束:
将状态对象声明为静态常量,有几个状态声明几个静态常量。
环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。
优点:
1.结构清晰,避免了过多的switch case或者if else,避免了程序复杂性,提高了系统可维护性。
2.很好的体现了开闭原则和单一职责原则,每个状态都是一个子类,增加状态就增加子类,修改状态就修改子类。
3.封装性好,状态变换放在类的内部,状态变换放在类的外部。
缺点:
子类太多容易类膨胀,一个事物状态太多就会有很多子类,不好管理,不过也好解决,比如在数据库中建立一个状态表。
使用场景:
行为随状态而改变的场景:状态机
条件语句的代替者。
注意事项:
行为在收到状态约束的情况下可以使用状态模式,但对象的状态最好不要超过5个。
状态需要自由切换时,需要考虑和建造者模式或其他模式混合使用,一般来说状态会有很多种,与其相对的是动作的组合模式也会很多,但动作不会增加。
代码示例:状态模式中也需要两个类相互包含,因此c++实现是需要注意写法,还是如之前博文中说的,分三步
1.声明所有类
2.声明类中函数和数据
3.类外实现函数
class Lift;
class StateOfLift;
class LiftOpen;
class LiftClose;
class LiftMove;
class LiftStop;
class Lift
{
public:
static StateOfLift* IsOpened;
static StateOfLift* IsClosed;
static StateOfLift* IsMoving;
static StateOfLift* IsStopped;
void Open();
void Close();
void Move();
void Stop();
void SetState(StateOfLift* stateOfLift);
protected:
StateOfLift* mStateOfLift;
};
class StateOfLift
{
public:
virtual void Open