目录
意图
- 允许对象在其内部状态发生变化时改变其行为。该对象将出现更改其类。
- 面向对象的状态机
- wrapper + 多态 wrappee + 协作
问题
单体对象的行为是其状态的函数,它必须在运行时根据该状态改变其行为。或者,一个应用程序的特点是大量的案例语句,这些语句基于应用程序的状态来引导控制流。
讨论
状态模式是解决如何使行为依赖于状态的问题。
- 定义一个“上下文”类来向外界呈现一个单一的界面。
- 定义一个 State 抽象基类。
- 将状态机的不同“状态”表示为 State 基类的派生类。
- 在适当的状态派生类中定义特定于状态的行为。
- 在“上下文”类中维护一个指向当前“状态”的指针。
- 要更改状态机的状态,请更改当前的“状态”指针。
状态模式没有指定状态转换的定义位置。选择有两个:“上下文”对象,或每个单独的 State 派生类。后一种选择的优点是易于添加新的 State 派生类。缺点是每个 State 派生类都知道(耦合到)其兄弟姐妹,这引入了子类之间的依赖关系。
设计有限状态机的表驱动方法可以很好地指定状态转换,但很难添加动作来伴随状态转换。基于模式的方法使用代码(而不是数据结构)来指定状态转换,但它在适应状态转换动作方面做得很好。
结构
状态机的接口封装在“包装器”类中。wrappee 层次结构的接口反映了包装器的接口,除了一个附加参数。额外的参数允许 wrappee 派生类在必要时回调包装类。否则会拖累包装类的复杂性被整齐地划分并封装在包装对象委托的多态层次结构中。

例子
状态模式允许对象在其内部状态发生变化时改变其行为。这种模式可以在自动售货机中观察到。自动售货机的状态基于库存、存入的货币数量、找零的能力、选择的物品等。当存入货币并做出选择时,自动售货机要么交付产品,不找零,交付产品和更改,由于存款货币不足而没有交付产品,或者由于库存耗尽而没有交付产品。

检查清单
- 识别一个现有的类,或者创建一个新的类,从客户的角度来看,它将充当“状态机”。该类是“包装”类。
- 创建一个复制状态机接口方法的 State 基类。每个方法都有一个附加参数:包装类的一个实例。State 基类指定任何有用的“默认”行为。
- 为每个域状态创建一个状态派生类。这些派生类只覆盖它们需要覆盖的方法。
- 包装类维护一个“当前”状态对象。
- 所有客户端对包装器类的请求都简单地委托给当前的 State 对象,并
this
传递包装器对象的指针。 - State 方法会根据需要更改包装对象中的“当前”状态。
经验法则
- 状态对象通常是单例。
- Flyweight 解释了何时以及如何共享 State 对象。
- 解释器可以使用状态来定义解析上下文。
- Strategy 有两种不同的实现方式,第一种类似于 State。不同之处在于绑定时间(策略是一次绑定模式,而状态则更具动态性)。
- State 和 Bridge 的结构是相同的(除了 Bridge 允许信封类的层次结构,而 State 只允许一个)。这两种模式使用相同的结构来解决不同的问题:State 允许对象的行为随着其状态而改变,而 Bridge 的目的是将抽象与其实现分离,以便两者可以独立变化。
- 状态模式的实现建立在策略模式之上。国家和战略之间的区别在于意图。使用 Strategy,算法的选择是相当稳定的。对于 State,“上下文”对象的状态变化会导致它从 Strategy 对象的“调色板”中进行选择。
本文来自转载,原文链接: