状态模式 (State Pattern)
什么是状态模式?
状态模式是一种行为型设计模式,它允许你在对象的内部状态改变时改变它的行为。对象看起来好像改变了它的类。
简单来说:状态模式就是让对象在不同状态下有不同的行为。
生活中的例子
想象一下:
- 订单状态:待支付、已支付、已发货、已完成
- 交通灯:红灯、黄灯、绿灯
- 游戏角色:正常、受伤、死亡
为什么需要状态模式?
传统方式的问题
java
// 使用if-else处理状态
if (state == "待支付") {
// 待支付逻辑
} else if (state == "已支付") {
// 已支付逻辑
} else if (state == "已发货") {
// 已发货逻辑
}
问题:
- 代码臃肿:大量if-else导致代码臃肿
- 难以扩展:新增状态需要修改代码
- 难以维护:状态逻辑分散在代码各处
状态模式的优势
java
// 使用状态模式
state.handle();
优势:
- 清晰分离:每个状态的行为清晰分离
- 易于扩展:新增状态很容易
- 易于维护:状态逻辑集中管理
状态模式的结构
┌─────────────────────┐
│ State │ 状态接口
├─────────────────────┤
│ + handle(): void │
└──────────┬──────────┘
│ 实现
├──┬──────────────────┬──────────────┐
│ │ │
┌──────────┴──────┐ ┌───────────┴───────┐ ┌───┴────────┐
│ ConcreteState1 │ │ ConcreteState2 │ │ ... │ 具体状态
├─────────────────┤ ├───────────────────┤ ├────────────┤
│ + handle() │ │ + handle() │ │ │
└─────────────────┘ └───────────────────┘ └────────────┘
┌─────────────────────┐
│ Context │ 上下文
├─────────────────────┤
│ - state: State │
│ + setState(): void │
│ + request(): void │
└─────────────────────┘
代码示例
1. 定义状态接口
java
/**
* 状态接口
*/
public interface State {
/**
* 处理请求
*/
void handle();
}
2. 定义具体状态
java
/**
* 具体状态:待支付状态
*/
public class PendingPaymentState implements State {
@Override
public void handle() {
System.out.println("订单状态:待支付,等待用户支付");
}
}
/**
* 具体状态:已支付状态
*/
public class PaidState implements State {
@Override
public void handle() {
System.out.println("订单状态:已支付,等待发货");
}
}
/**
* 具体状态:已发货状态
*/
public class ShippedState implements State {
@Override
public void handle() {
System.out.println("订单状态:已发货,等待收货");
}
}
/**
* 具体状态:已完成状态
*/
public class CompletedState implements State {
@Override
public void handle() {
System.out.println("订单状态:已完成");
}
}
3. 定义上下文
java
/**
* 上下文:订单
*/
public class Order {
private State state;
public Order() {
this.state = new PendingPaymentState();
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle();
}
}
4. 使用状态
java
/**
* 状态模式测试类
* 演示如何使用状态模式管理订单状态
*/
public class StateTest {
public static void main(String[] args) {
System.out.println("=== 状态模式测试 ===\n");
// 创建订单
Order order = new Order();
// 测试不同状态
System.out.println("--- 待支付状态 ---");
order.request();
System.out.println("\n--- 已支付状态 ---");
order.setState(new PaidState());
order.request();
System.out.println("\n--- 已发货状态 ---");
order.setState(new ShippedState());
order.request();
System.out.println("\n--- 已完成状态 ---");
order.setState(new CompletedState());
order.request();
System.out.println("\n=== 状态模式的优势 ===");
System.out.println("1. 清晰分离:每个状态的行为清晰分离");
System.out.println("2. 易于扩展:新增状态很容易");
System.out.println("3. 易于维护:状态逻辑集中管理");
System.out.println("4. 避免条件语句:避免大量if-else");
System.out.println("\n=== 实际应用场景 ===");
System.out.println("1. 订单系统:订单状态管理");
System.out.println("2. 游戏开发:角色状态管理");
System.out.println("3. 工作流:工作流状态管理");
System.out.println("4. 交通灯:交通灯状态管理");
System.out.println("\n=== 与策略模式的区别 ===");
System.out.println("状态模式:对象在不同状态下有不同的行为");
System.out.println("策略模式:对象在不同策略下有不同的行为");
System.out.println("状态模式:状态之间有转换关系");
System.out.println("策略模式:策略之间没有转换关系");
}
}
状态模式的优点
- 清晰分离:每个状态的行为清晰分离
- 易于扩展:新增状态很容易
- 易于维护:状态逻辑集中管理
- 避免条件语句:避免大量if-else
状态模式的缺点
- 类数量增加:每个状态都需要一个类
- 状态转换复杂:状态转换可能比较复杂
适用场景
- 多个状态:对象有多个状态
- 状态依赖:行为依赖于状态
- 状态转换:状态需要频繁转换
常见应用场景
- 订单系统:订单状态管理
- 游戏开发:角色状态管理
- 工作流:工作流状态管理
使用建议
- 多个状态:使用状态模式
- 状态依赖:使用状态模式
- 简单状态:直接使用if-else即可
注意事项
⚠️ 状态模式虽然有用,但要注意:
- 不要让状态转换过于复杂
- 考虑使用状态机