状态模式(State Pattern)
状态模式(State Pattern)
定义
状态模式(State Pattern) 是一种行为设计模式,允许对象在其 内部状态改变时改变它的行为,使对象看起来像是修改了自身的类。该模式通过将状态相关的行为封装到独立的类中,消除复杂的条件判断逻辑,提升代码可维护性。
核心思想
-
状态与行为绑定:将每个状态的行为封装到独立类中,避免 if-else 或 switch-case 的泛滥。
-
动态切换状态:对象通过委托调用当前状态类的方法,状态变更时自动切换行为逻辑。
-
开闭原则:新增状态时无需修改现有代码,只需添加新的状态类。
模式结构
角色 | 职责 |
---|---|
Context | 上下文类,持有当前状态对象,定义客户端交互接口。 |
IState | 状态接口,声明状态相关的操作方法(如 Handle())。 |
ConcreteState | 具体状态类,实现 IState 接口,定义该状态下的具体行为逻辑。 |
主要解决的问题
-
消除复杂条件分支:将状态相关的逻辑分散到独立的类中,避免代码臃肿。
-
状态转换透明化:通过状态对象管理状态迁移逻辑,使代码更清晰易维护。
-
支持动态扩展:新增状态时无需修改现有状态类和上下文类。
代码示例
场景描述
模拟电梯(Elevator)的状态切换:
- 电梯有 开门(Open)、关门(Close)、运行(Run)、停止(Stop) 四种状态。
- 不同状态下,电梯对同一操作(如按下按钮)的响应不同。
实现代码
using System;
// 状态接口
interface IElevatorState
{
void Handle(Elevator elevator);
}
// 具体状态:开门状态
class OpenState : IElevatorState
{
public void Handle(Elevator elevator)
{
Console.WriteLine("电梯门已打开,无法移动。");
// 切换到关门状态
elevator.SetState(new CloseState());
}
}
// 具体状态:关门状态
class CloseState : IElevatorState
{
public void Handle(Elevator elevator)
{
Console.WriteLine("电梯门已关闭,准备运行。");
// 切换到运行状态
elevator.SetState(new RunState());
}
}
// 具体状态:运行状态
class RunState : IElevatorState
{
public void Handle(Elevator elevator)
{
Console.WriteLine("电梯正在运行,即将到达目标楼层。");
// 切换到停止状态
elevator.SetState(new StopState());
}
}
// 具体状态:停止状态
class StopState : IElevatorState
{
public void Handle(Elevator elevator)
{
Console.WriteLine("电梯已停止,准备开门。");
// 切换到开门状态
elevator.SetState(new OpenState());
}
}
// 上下文类:电梯
class Elevator
{
private IElevatorState _currentState;
public Elevator()
{
// 初始状态为停止状态
_currentState = new StopState();
}
// 设置当前状态
public void SetState(IElevatorState state)
{
_currentState = state;
}
// 触发状态行为(例如用户按下按钮)
public void PressButton()
{
_currentState.Handle(this);
}
}
// 客户端调用
class Program
{
static void Main()
{
Elevator elevator = new Elevator();
// 模拟用户多次按下按钮
elevator.PressButton(); // 停止 → 开门
elevator.PressButton(); // 开门 → 关门
elevator.PressButton(); // 关门 → 运行
elevator.PressButton(); // 运行 → 停止
}
}
输出结果
电梯已停止,准备开门。
电梯门已打开,无法移动。
电梯门已关闭,准备运行。
电梯正在运行,即将到达目标楼层。
总结
优点
-
代码清晰:状态逻辑分散到独立类中,避免条件分支嵌套。
-
高扩展性:新增状态只需添加新类,无需修改现有代码。
-
封装状态迁移:状态切换逻辑由具体状态类自行管理,上下文类无需关心细节。
缺点
-
类数量膨胀:状态较多时会导致类的数量增加。
-
状态迁移复杂度:若状态转换逻辑复杂,可能需要额外的协调机制。