State(状态)–对象行为型模式
一、意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
二、动机
1.在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
2.如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
三、适用性
1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,者一对象可以不依赖于其他对象而独立的变化。
四、结构
五、效果
1.它将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。 State模式将所有于一个特定的状态相关的行为都放入一个对象中。因为所有于状态相关的代码都存在于某一个State子类中,所以通过定义新的子类可以很容易的增加新的状态和转换。
2.它使得状态转化显式化。 当一个对象仅以内部数据值来定义当前状态时,其状态仅表现为对一些变量的赋值,这不够明确。为不同的状态引入独立的对象使得转换变得更加明确。而且,State对象可保证Context不会发生内部状态不一致的情况,因为从Context的角度看,状态转换是原子的——只需要重新绑定一个变量(即Context的State对象变量),而无需为对个变量赋值。
3.State对象可被共享。 如果State对象没有实例变量——即他们表示的状态完全以他们的类型来编码——那么各Context对象可以共享一个State对象。当状态以这种方式被共享时,他们必然没有内部状态,只有行为的轻量级对象。
六、实现
1.谁定义状态转换。 State模式不指定哪个一参与者定义状态转换准则。如果该准则是固定的,那么他们可在Context中完全实现。然而若让State子类自身指定他们的后继状态以及何时进行转换,通常更灵活更合适,这需要Context增加一个接口,让State对象显示地设定Context的当前状态。
用这种方法分散转换逻辑可言很容易地定义新的State子类来修改和扩展该逻辑。这样做的一个缺点是,一个State子类至少拥有一个其他子类信息,这就在个子类之间产生了实现依赖。
2.基于表的另一种方式。
3.创建和销毁State对象。 一个常见的值得考虑的实现上的权衡是,究竟是(1)仅需要State对象是才创建他们并随后销毁他们,还是(2)提前创建他们并且始终不销毁他们。
4.使用动态继承。
七、要点总结
1.State模式将所有于一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作于状态转换之间的解耦。
2.为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换时原子性的——即要么彻底转换过来,要么不转换。
3.如果State对象没有实例变量,那么各个上下文可以共享一个State对象,从而节省对象开销。
八、相关模式
Flyweight模式解释了何时以及怎样共享状态对象。
状态对象通常是Singleton。
九、举例说明
人醉酒时的状态和平时的状态。
本文为李建忠设计模式视频的笔记以及《设计模式-可复用面向对象的软件的基础》和自己的部分见解