状态模式(Java实现)
状态模式定义一套流程,用来变更对象的内部状态,以影响该对象的内部行为。这个模式属于经典的 GoF 设计模式。
对象的状态可以用有限状态机(finite state machine)这一概念来表示。状态模式使得对象能够合理地变更其内部状态,进而变更其内部行为。这个模式要求我们用特定的类来描述对象所处的某种内部状态,并让这些状态类的实例负责处理对象在各状态下所应表现出的行为。
JDK 在实现 jlink 插件的时候用到了状态模式,这个插件位于 jdk.jlink 模块的 jdk.tools.jlink.plugin 包中。这个包里有个名为 Plugin 的接口,用来描述 jlink 插件所应实现的功能,这个接口定义了一个名为 State 的嵌套枚举类,该类的各个枚举值与插件的各种状态相对应。
举一个例子,假设车辆有各种状态,这些状态都由相应的状态类来表示:

图 1 用UML类图演示各种状态类之间的关系
对象的内部状态除了影响该对象在此状态下的内部运作方式,还有可能让程序的外在行为,以及其他对象与该对象之间的交互方式发生变化。
对象的状态可以用有限状态机(finite state machine)这一概念来表示。状态模式使得对象能够合理地变更其内部状态,进而变更其内部行为。这个模式要求我们用特定的类来描述对象所处的某种内部状态,并让这些状态类的实例负责处理对象在各状态下所应表现出的行为。
JDK 在实现 jlink 插件的时候用到了状态模式,这个插件位于 jdk.jlink 模块的 jdk.tools.jlink.plugin 包中。这个包里有个名为 Plugin 的接口,用来描述 jlink 插件所应实现的功能,这个接口定义了一个名为 State 的嵌套枚举类,该类的各个枚举值与插件的各种状态相对应。
举一个例子,假设车辆有各种状态,这些状态都由相应的状态类来表示:
public static void main(String[] args) { System.out.println("State Pattern, vehicle turn on states"); ... var initState = new InitState(); var startState = new StartState(); var stopState = new StopState(); vehicle.setState(initState); System.out.println("Vehicle state2:" + vehicle.getState()); vehicle.setState(startState); System.out.println("Vehicle state3:" + vehicle.getState()); vehicle.setState(stopState); System.out.println("Vehicle state4:" + vehicle.getState()); }程序输出结果为:
State Pattern, vehicle turn on states
Vehicle state2:InitState{vehicle=truck}
Vehicle state3:StartState{vehicle=truck}
Vehicle state4:StopState{vehicle=truck}

图 1 用UML类图演示各种状态类之间的关系
总结
状态模式让我们看到用具体的类来表示对象的各种状态会有哪些好处。这样做使得程序更容易测试,也让底层代码变得比原来更加容易维护,因为每一种状态都清晰地封装成了对应的状态类,这些类都符合 SOLID 设计理念中的单一责任原则(SRP)。有了这样的设计,用户就能够便捷地发出状态切换命令,而不用再手工编写代码来处理与之相关的异常了。对象的内部状态除了影响该对象在此状态下的内部运作方式,还有可能让程序的外在行为,以及其他对象与该对象之间的交互方式发生变化。