为了巩固跟复习22个设计模式,每天不定时发表一篇关于设计模式的文稿!今天写的是行为模式中的“状态模式!
- 定义
状态模式是一种行为模式,让你能在一个对象的内部状态变化时该变其行为,使其看上去就像改变了自身所属的类一样。
- 状态模式结构
![f1e546ab44dd4e90ca604e3618c5ccec.png](https://i-blog.csdnimg.cn/blog_migrate/35361749e793d4f142b4d514c24865d8.jpeg)
状态模式结构
- 上下文(Context)保存了对于一个具体状态对象的引用,并会将所有与改状态相关的工作委派给他,上下文通过状态接口与状态对象交互,且会提供一个设置器用于传递新的状态对象。
- 状态(State)接口会声明特定于状态的方法。这些方法应能被其他所有具体状态所理解,因为你不希望某些状态所拥有的方法永远不会被调用。
- 具体状态(Concrete States)会自行实现特定于状态的方法。为了避免多个状态中包含相似代码,你可以提供一个封装有部分通用行为的中间抽象类。状态对象可存储于上细纹的反向引用。状态可以通过该引用从上下文处获取所需信息。并且能触发状态转移。
- 上下文和具体状态都可以设置上文的下个状态,并且通过替换连接到上文的状态对象来完成实际的状态转换。
- 适应场景
- 如果对象需要根据自身当前状态进行不同行为,同时状态的数量非常多且与状态相关的代码会频繁变更的话,可以使用状态模式。
- 如果某个类需要根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时,可使用该模式。
- 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。
- 实现方式
- 确定哪些类是上下文。 它可能是包含依赖于状态的代码的已有类; 如果特定于状态的代码分散在多个类中, 那么它可能是一个新的类。
- 声明状态接口。 虽然你可能会需要完全复制上下文中声明的所有方法, 但最好是仅把关注点放在那些可能包含特定于状态的行为的方法上。
- 为每个实际状态创建一个继承于状态接口的类。 然后检查上下文中的方法并将与特定状态相关的所有代码抽取到新建的类中。在将代码移动到状态类的过程中, 你可能会发现它依赖于上下文中的一些私有成员。 你可以采用以下几种变通方式:将这些成员变量或方法设为公有。将需要抽取的上下文行为更改为上下文中的公有方法, 然后在状态类中调用。 这种方式简陋却便捷, 你可以稍后再对其进行修补。将状态类嵌套在上下文类中。 这种方式需要你所使用的编程语言支持嵌套类。
- 在上下文类中添加一个状态接口类型的引用成员变量, 以及一个用于修改该成员变量值的公有设置器。
- 再次检查上下文中的方法, 将空的条件语句替换为相应的状态对象方法。
- 为切换上下文状态, 你需要创建某个状态类实例并将其传递给上下文。 你可以在上下文、 各种状态或客户端中完成这项工作。 无论在何处完成这项工作, 该类都将依赖于其所实例化的具体类。
- 状态模式优缺点
优点:1)单一职责原则。将与特定状态相关的代码放到单独的类中。
2)开闭原则。无需修改已有状态类和上下文就能引入新状态。
3)通过消除臃肿的状态机条件语句简化上下文代码。
缺点:1) 如果状态机只有很少的几个状态,或者很少发生改变,那么应用该模式可能会显得小题大作。
- 在Java中状态模式的应用
这里是核心 Java 程序库中一些状态模式的示例:
* javax.faces.lifecycle.LifeCycle#execute() (由 FacesServlet控制: 行为依赖于当前 JSF 生命周期的阶段 (状态))
- 如何识别状态模式
状态模式可通过受外部控制且能根据对象状态改变行为的方法来识别。