【设计模式】 状态模式

1、定义

1.1 标准定义

  其定义如下:
  Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.(当一个对象内在状态改变时允许其改变行为, 这个对象看起来像改变了其类。)

  状态模式的核心是封装, 状态的变更引起了行为的变更, 从外部看起来就好像这个对象对应的类发生了改变一样。

1.2 通用类图

  ● State——抽象状态角色
  接口或抽象类, 负责对象状态定义, 并且封装环境角色以实现状态切换。

  ● ConcreteState——具体状态角色
  每一个具体状态必须完成两个职责: 本状态的行为管理以及趋向状态处理, 通俗地说,就是本状态下要做的事情, 以及本状态如何过渡到其他状态。

  ● Context——环境角色
  定义客户端需要的接口, 并且负责具体状态的切换。

2、实现

2.1 类图

  Context:定义客户端感兴趣的接口,并且维护一个ConcreteState子类的实例,这个实例定义当前状态;
  State:定义一个接口以封装与Context的一个特定状态相关的行为;
  ConcreteState subclasses:每一个子类实现一个与Context的一个状态相关的行为。

2.2 代码

#include <iostream>
using namespace std;

class Context;

class State
{
public:
   // 状态处理,此处可以选择是否切换到其他状态
virtual void Handle(Context *pContext) = 0; }; class ConcreteStateA : public State { public: virtual void Handle(Context *pContext) { cout<<"I am concretestateA."<<endl; } }; class ConcreteStateB : public State { public: virtual void Handle(Context *pContext) { cout<<"I am concretestateB."<<endl; } }; class Context { public: Context(State *pState) : m_pState(pState){} void Request() { if (m_pState) { m_pState->Handle(this); } } void ChangeState(State *pState) { m_pState = pState; } private: State *m_pState; }; int main() { State *pStateA = new ConcreteStateA(); State *pStateB = new ConcreteStateB(); Context *pContext = new Context(pStateA); pContext->Request(); pContext->ChangeState(pStateB); pContext->Request(); delete pContext; delete pStateB; delete pStateA; }

3、总结

3.1 优点

  ● 结构清晰
  避免了过多的switch...case或者if...else语句的使用, 避免了程序的复杂性,提高系统的可维护性。

  ● 遵循设计原则
  很好地体现了开闭原则和单一职责原则, 每个状态都是一个子类, 你要增加状态就要增加子类, 你要修改状态, 你只修改一个子类就可以了。

  ● 封装性非常好
  这也是状态模式的基本要求, 状态变换放置到类的内部来实现, 外部的调用不用知道类内部如何实现状态和行为的变换。

3.2 缺点

  状态模式既然有优点, 那当然有缺点了。 但只有一个缺点, 子类会太多, 也就是类膨胀。 

3.3 使用场景

  ● 行为随状态改变而改变的场景
  这也是状态模式的根本出发点, 例如权限设计, 人员的状态不同即使执行相同的行为结果也会不同, 在这种情况下需要考虑使用状态模式。

  ● 条件、 分支判断语句的替代者
  在程序中大量使用switch语句或者if判断语句会导致程序结构不清晰, 逻辑混乱, 使用状态模式可以很好地避免这一问题, 它通过扩展子类实现了条件的判断处理。

3.4 注意事项

  状态模式适用于当某个对象在它的状态发生改变时, 它的行为也随着发生比较大的变化, 也就是说在行为受状态约束的情况下可以使用状态模式, 而且使用时对象的状态最好不要超过5个。 

原文地址:https://www.cnblogs.com/ChinaHook/p/7309215.html