在软件开发中,很多对象的行为会随着其内部状态的变化而改变。如果将所有状态逻辑写在一个类中,代码不仅臃肿而且难以维护。**状态模式(State Pattern)**正是为了解决这个问题而设计的。通过将对象的状态封装成独立的状态类,并将状态相关的行为转移到这些状态类中,状态模式让对象在内部状态发生变化时自动切换行为,达到了将状态转换与行为实现分离的目的。
本文将详细介绍状态模式的核心思想、基本结构与优缺点,并通过多个示例展示状态模式在不同场景下的应用,包括交通信号灯、自动售货机、UI 按钮状态以及游戏角色状态等多个方面。
状态模式简介
状态模式是一种行为型设计模式,其主要思想是将对象在不同状态下的行为封装到不同的状态类中,并通过上下文(Context)对象维护当前状态。当上下文状态发生变化时,它会将请求委托给当前状态对象,从而使得对象的行为随着状态的改变而改变。
例如,一个交通信号灯对象,根据当前状态(红灯、绿灯、黄灯)的不同,会执行不同的操作;而一个自动售货机在“无硬币”、“有硬币”和“售出商品”等状态下,其响应行为也各不相同。状态模式通过分离状态逻辑,使得代码更易维护和扩展。
状态模式的结构与特点
主要角色:
-
上下文(Context)
维护一个对当前状态对象的引用,并委托状态对象处理请求。 -
状态接口(State Interface)
定义状态对象必须实现的方法,通常是与上下文相关的行为。 -
具体状态(Concrete State)
实现状态接口的类,每个类代表一种状态,并封装在该状态下的行为。
特点:
- 状态封装:将与状态相关的行为封装到独立的状态类中,使得状态变化与行为实现解耦。
- 行为动态切换:上下文对象通过持有状态对象的引用,根据内部状态的变化动态切换行为。
- 易于扩展:增加新状态只需增加新的具体状态类,而无需修改上下文类代码。
JavaScript 实现示例
下面通过多个示例展示如何在 JavaScript 中使用状态模式。
示例 1:交通信号灯
交通信号灯根据当前状态(红灯、绿灯、黄灯)的不同,执行不同的动作,并在状态之间循环切换。
// 定义状态接口及具体状态类
class TrafficLightState {
constructor(context) {
this.context = context;
}
handle() {
throw n