状态模式
状态模式(State Pattern)是一种行为型设计模式,核心思想是让对象的行为随内部状态动态变化,通过将状态抽象为独立类,消除复杂的条件判断逻辑,实现状态与行为的解耦。类似于红绿灯:红灯停、绿灯行,状态切换时行为自动变化,但控制逻辑本身无需修改。
一、通俗理解
以电梯控制为例:
- 传统方式:用
if-else
判断电梯当前状态(运行、停止、故障),代码臃肿且难以扩展新状态。 - 状态模式:
- 状态接口:定义电梯的通用操作(开门、关门、运行)。
- 具体状态:运行状态禁止开门,停止状态允许开门等,每个状态独立实现行为。
- 上下文对象(电梯控制器):持有当前状态对象,调用时自动执行对应逻辑。
当电梯从“停止”切换到“运行”时,只需更换状态对象,无需修改控制器代码。
二、模式结构
- 上下文(Context):维护当前状态对象(如电梯控制器),触发状态行为。
- 抽象状态(State):定义状态行为接口(如
openDoor()
)。 - 具体状态(ConcreteState):实现特定状态下的行为(如运行中禁止开门)。
三、适用场景
- 多状态依赖行为:订单状态(待支付→已发货)、游戏角色(站立→跳跃)。
- 消除复杂条件分支:替代大量
if-else
或switch-case
语句。 - 动态状态切换:如物联网设备(空调制冷/制热模式切换)。
四、代码实现
1. C++ 示例(电梯控制)
#include <iostream>
// 抽象状态:电梯行为接口
class ElevatorState {
public:
virtual void openDoor() = 0;
virtual void closeDoor() = 0;
virtual ~ElevatorState() = default;
};
// 具体状态:停止状态
class StoppedState : public ElevatorState {
public:
void openDoor() override { std::cout << "电梯门已打开\n"; }
void closeDoor() override { std::cout << "电梯门已关闭\n"; }
};
// 具体状态:运行状态
class RunningState : public ElevatorState {
public:
void openDoor() override { std::cout << "错误:运行中禁止开门!\n"; }
void closeDoor() override { std::cout << "电梯门已关闭\n"; }
};
// 上下文:电梯控制器
class Elevator {
ElevatorState* state;
public:
Elevator() : state(new StoppedState()) {}
void setState(ElevatorState* newState) {
delete state;
state = newState;
}
void pressOpenButton() { state->openDoor(); }
~Elevator() { delete state; }
};
int main() {
Elevator elevator;
elevator.pressOpenButton(); // 输出:电梯门已打开
elevator.setState(new RunningState());
elevator.pressOpenButton(); // 输出:错误:运行中禁止开门!
}
解析:
- 状态切换通过
setState()
实现,行为逻辑封装在具体状态类中。
2. Python 示例(自动售货机)
from abc import ABC, abstractmethod
class VendingMachineState(ABC):
@abstractmethod
def insert_coin(self, machine):
pass
# 待投币状态
class IdleState(VendingMachineState):
def insert_coin(self, machine):
print("投币成功!")
machine.state = HasMoneyState()
# 已投币状态
class HasMoneyState(VendingMachineState):
def select_product(self, machine):
print("出货成功!")
machine.state = IdleState()
class VendingMachine:
def __init__(self):
self.state = IdleState()
def insert_coin(self):
self.state.insert_coin(self)
# 客户端
vm = VendingMachine()
vm.insert_coin() # 投币成功!
特点:
- Python利用鸭子类型简化接口继承,状态转换由具体状态类触发。
3. Java 示例(订单状态流转)
// 状态接口
interface OrderState {
void handle(OrderContext context);
}
// 待支付状态
class UnpaidState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单待支付");
context.setState(new PaidState());
}
}
// 上下文
class OrderContext {
private OrderState state;
public OrderContext() {
this.state = new UnpaidState();
}
public void setState(OrderState state) {
this.state = state;
}
public void process() {
state.handle(this);
}
}
// 测试
public class Client {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.process(); // 输出:订单待支付 → 切换到已支付状态
}
}
应用场景:
- 电商订单状态管理,符合开闭原则(新增状态只需添加类)。
五、优缺点分析
优点 | 缺点 |
---|---|
1. 消除条件分支:简化复杂逻辑判断 | 1. 类数量膨胀:每个状态需单独类 |
2. 扩展性强:新增状态无需修改旧代码 | 2. 状态转换复杂:需管理状态间切换规则 |
3. 职责清晰:每个状态类专注自身逻辑 | 3. 性能开销:频繁切换可能影响效率 |
六、总结
状态模式通过封装状态行为实现动态行为切换,核心价值在于:
- 解耦思维:状态与行为分离,提升代码可维护性。
- 灵活扩展:新增状态只需添加类,符合开闭原则(如电梯新增“维修状态”)。
- 实际应用:广泛用于订单系统、游戏角色控制、物联网设备。
扩展对比:
- 与策略模式:策略模式主动选择算法,状态模式被动响应状态变化。
- 优化技巧:对简单场景可使用枚举简化,复杂场景搭配状态机管理转换规则。