文章目录
- 前言
- 一、概念
- 二、核心结构
- [三、Java 代码实现(订单状态流转)](#三、Java 代码实现(订单状态流转))
-
- [1. 抽象状态](#1. 抽象状态)
- [2. 具体状态:待支付](#2. 具体状态:待支付)
- [3. 具体状态:已支付](#3. 具体状态:已支付)
- [4. 具体状态:已发货](#4. 具体状态:已发货)
- [5. 具体状态:已完成](#5. 具体状态:已完成)
- [6. 上下文(订单)](#6. 上下文(订单))
- [7. 客户端测试](#7. 客户端测试)
- [四、状态模式 VS 策略模式(高频面试)](#四、状态模式 VS 策略模式(高频面试))
- 五、优缺点
- 六、应用场景
- 七、总结
前言
开发中经常遇到对象行为随状态不同而变化 的场景:订单(待支付/已支付/已发货/已完成)、线程(新建/就绪/运行/阻塞/结束)、电梯(开门/关门/运行/停止)。如果用大量 if-else/switch 判断状态,代码臃肿、难以维护、极易出错。状态模式 就是专门解决多状态多行为、状态流转复杂的行为型设计模式。
一、概念
状态模式(State Pattern) 是一种行为型设计模式 ,核心思想:
允许对象在内部状态改变时改变其行为,对象看起来好像修改了它的类。
简单理解:
- 把每种状态 封装成独立的状态类;
- 状态不同,行为完全不同;
- 状态切换由状态自身或上下文管理;
- 彻底消灭
if-else/switch。
一句话总结:
状态决定行为,状态变,行为就变。
二、核心结构
- Context(上下文)
维护当前状态,将请求委托给当前状态处理。 - State(抽象状态)
定义状态对应的行为接口。 - ConcreteState(具体状态)
实现各自状态下的行为,并负责状态切换。
三、Java 代码实现(订单状态流转)
订单状态流转:
待支付 → 已支付 → 已发货 → 已完成
1. 抽象状态
java
public interface OrderState {
void handle(OrderContext context);
}
2. 具体状态:待支付
java
public class WaitPayState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("当前状态:待支付 → 执行支付逻辑");
context.setState(new PaidState()); // 切换为已支付
}
}
3. 具体状态:已支付
java
public class PaidState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("当前状态:已支付 → 发货");
context.setState(new DeliverState()); // 切换为已发货
}
}
4. 具体状态:已发货
java
public class DeliverState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("当前状态:已发货 → 确认收货");
context.setState(new FinishState()); // 切换为已完成
}
}
5. 具体状态:已完成
java
public class FinishState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("当前状态:已完成 → 订单结束");
// 无后续状态
}
}
6. 上下文(订单)
java
public class OrderContext {
private OrderState state;
public OrderContext() {
// 初始状态:待支付
state = new WaitPayState();
}
public void setState(OrderState state) {
this.state = state;
}
// 执行当前状态行为
public void process() {
state.handle(this);
}
}
7. 客户端测试
java
public class Client {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.process(); // 待支付 → 已支付
order.process(); // 已支付 → 已发货
order.process(); // 已发货 → 已完成
order.process(); // 已完成
}
}
输出:
当前状态:待支付 → 执行支付逻辑
当前状态:已支付 → 发货
当前状态:已发货 → 确认收货
当前状态:已完成 → 订单结束
四、状态模式 VS 策略模式(高频面试)
| 对比点 | 状态模式 | 策略模式 |
|---|---|---|
| 关注点 | 状态流转、行为随状态自动变化 | 算法可互换、平级替换 |
| 切换方式 | 状态自动切换 | 客户端主动设置 |
| 关系 | 状态之间有流转依赖 | 策略之间平等独立 |
| 典型场景 | 订单状态、线程状态、电梯状态 | 支付、促销、排序 |
五、优缺点
优点
- 消除大量 if-else/switch,结构清晰
- 状态职责集中,每个状态只做自己的事
- 状态切换安全、可控
- 符合开闭原则,新增状态只需加类
缺点
- 状态多会导致类数量爆炸
- 状态流转复杂时,设计难度上升
六、应用场景
- 订单状态、支付状态、物流状态
- 线程生命周期(NEW/RUNNABLE/BLOCKED/...)
- 电梯、门、游戏角色状态
- 工作流、审批流状态
- UI 控件状态(可用/禁用/聚焦)
经典框架:
- Spring Statemachine
- Quartz 任务状态
- Netty pipeline 状态
七、总结
- 状态模式 = 状态封装 + 行为随状态自动变化
- 核心:状态决定行为,状态变,行为就变
- 结构:
Context+State+ 具体状态类 - 最适合:多状态、多行为、状态流转复杂场景