behavioral_patterns/state.rst
.. _state:
.. contents:: 目录
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
在UML中可以使用状态图来描述对象状态的变化。
状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
状态模式包含如下角色:
.. image:: /_static/State.jpg
.. image:: /_static/seq_State.jpg
既然是状态模式,加上状态图,对状态转换间的理解会清晰很多:
.. image:: /_static/State1.png
.. literalinclude:: /code/State/main.cpp :language: cpp :linenos: :lines: 1-
.. literalinclude:: /code/State/Context.h :language: cpp :linenos: :lines: 1- :emphasize-lines: 20-24
.. literalinclude:: /code/State/Context.cpp :language: cpp :linenos: :lines: 1- :emphasize-lines: 19-25
.. literalinclude:: /code/State/ConcreteStateA.h :language: cpp :linenos: :lines: 1-
.. literalinclude:: /code/State/ConcreteStateA.cpp :language: cpp :linenos: :lines: 1- :emphasize-lines: 30-33
运行结果:
.. image:: /_static/State_run.jpg
在状态模式结构中需要理解环境类与抽象状态类的作用:
TCPConnection
这个示例来自《设计模式》,展示了一个简化版的TCP协议实现; TCP连接的状态有多种可能,状态之间的转换有相应的逻辑前提; 这是使用状态模式的场合;
状态图:
.. image:: /_static/State2.png
结构图:
.. image:: /_static/State_eg.jpg
时序图:
.. image:: /_static/seq_State_eg.jpg
状态模式的优点
状态模式的缺点
在以下情况下可以使用状态模式:
状态模式在工作流或游戏等类型的软件中得以广泛使用,甚至可以用于这些系统的核心功能设计,如在政府OA办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态,而且批文状态不同时对批文的操作也有所差异。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。
共享状态
简单状态模式与可切换状态的状态模式 1) 简单状态模式:简单状态模式是指状态都相互独立,状态之间无须进行转换的状态模式,这是最简单的一种状态模式。对于这种状态模式,每个状态类都封装与状态相关的操作,而无须关心状态的切换,可以在客户端直接实例化状态类,然后将状态对象设置到环境类中。如果是这种简单的状态模式,它遵循“开闭原则”,在客户端可以针对抽象状态类进行编程,而将具体状态类写到配置文件中,同时增加新的状态类对原有系统也不造成任何影响。 2) 可切换状态的状态模式:大多数的状态模式都是可以切换状态的状态模式,在实现状态切换时,在具体状态类内部需要调用环境类Context的setState()方法进行状态的转换操作,在具体状态类中可以调用到环境类的方法,因此状态类与环境类之间通常还存在关联关系或者依赖关系。通过在状态类中引用环境类的对象来回调环境类的setState()方法实现状态的切换。在这种可以切换状态的状态模式中,增加新的状态类可能需要修改其他某些状态类甚至环境类的源代码,否则系统无法切换到新增状态。