5.8-State「Object for state」-状态-状态对象-行为型模式
目的
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
示例
考虑一个表示网络连接的类 TCPConnection。
一个 TCPConnection 对象的状态处于若干不同状态之一:连接已建立(Established)、正在监听(Listening)、连接已关闭(Closed)。
当一个 TCPConnection 对象收到其他对象的请求时,它根据自身的当前状态做出不同的反应。

State 模式:
- Key:引入了一个称为 TCPState 的抽象类来表示网络的连接状态:
- TCPState 类为各表示不同的操作状态的子类声明了一个公共接口。
- TCPState 的子类实现与特定状态相关的行为
- TCPConnection 类维护一个表示 TCP 连接当前状态的状态对象(TCPState 子类的实例)
- 将所有与状态相关的请求委托给该对象
- 一旦连接状态改变,TCPConnection 对象就会改变它所使用的状态对象
适用性
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
- State 模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化
结构

- Context:定义面向客户的接口
- 维护 ConcreteState 实例,表征当前状态
- State:定义接口,封装与 Context 的特定状态相关的行为
- ConcreteStateX:每一子类实现一个与 Context 的一个状态相关的行为
关联
- Context 将与状态相关的请求委托给当前的 ConcreteState 对象处理。
- Context 可将自身作为一个参数传递给处理该请求的状态对象。这使得状态对象在必要时可访问 Context。
- Context 是客户使用的主要接口。客户可用状态对象来配置一个 Context,一旦一个 Context 配置完毕,它的客户不再需要直接与状态对象打交道。
- Context 或 ConcreteState 子类都可决定哪个状态是另外一个的后继者,以及是在何种条件下进行状态转换。
效果
将不同状态的行为分割开来:
- 不用 State 模式:使用数据值定义内部状态并且让 Context 操作来显式地检查这些数据。但这样将会使整个 Context 的实现中遍布看起来很相似的条件语句或 case 语句
- 使用 State 模式:
- 避免了庞大的条件语句
- 每一个状态转换和动作封装到一个类中,就把着眼点从执行状态提高到整个对象的状态。这将使代码结构化并使其意图更加清晰。
确保内部状态变量的一致性:从 Context 的角度看,状态转换是原子的——只需重新绑定一个 ConcreteState 实例,而无需为一组变量分别赋值。(仅以内部数据值来定义当前状态时,其状态仅表现为对一些变量的赋值)
State 对象可被共享:当状态以这种方式被共享时,它们必然是没有内部状态而只有行为的轻量级对象