项目背景:订单状态机的自动流转
在电商、外卖、物流等系统中,订单的状态流转 是核心业务逻辑之一。例如,在电商系统中,订单可能经历以下状态:
1️⃣ NEW(待支付) → 2️⃣ PAID(已支付) → 3️⃣ SHIPPED(已发货) → 4️⃣ DELIVERED(已签收) → 5️⃣ COMPLETED(交易完成)
在实际业务中,订单状态的变化通常是由用户操作或系统事件触发,如:
- 用户付款后,订单进入 PAID 状态
- 商家发货后,订单进入 SHIPPED 状态
- 用户签收后,订单进入 DELIVERED 状态
- 系统自动确认收货,订单进入 COMPLETED 状态
在传统设计中,订单状态流转可能是:
- 硬编码 if-else 处理状态 → 代码臃肿,不易维护
- 数据库存储状态映射 → 需要额外查询表结构,增加复杂性
- 手动触发每个状态 → 不能自动流转,可能导致状态遗漏
本项目的目标是:
✅ 设计 清晰、可扩展的订单状态机 ,支持 自动流转
✅ 采用 责任链模式 ,确保事件自动推进
✅ 采用 策略模式,解耦不同状态的处理逻辑
这样,我们只需要调用 handleEvent(OrderEvent.PAY)
,系统就能 自动执行后续所有状态转换,直到订单完成!
设计思路
1️⃣ 设计 OrderState
枚举
-
每个订单状态(如
NEW
、PAID
)需要:- 对应的处理器类 (即
OrderStateHandler
实现) - 触发的事件 (如
PAY
触发PAID
状态)
- 对应的处理器类 (即
-
维护 事件到下一个状态的映射,保证状态自动流转。
2️⃣ 设计 OrderStateHandler
(策略模式)
- 不同状态执行不同逻辑 (如 支付订单、发货订单)。
- 通过 工厂模式 动态实例化具体的
Handler
。
3️⃣ 设计 OrderStateMachine
(责任链模式)
- 调用
handleEvent(OrderEvent.PAY)
即可自动完成整个状态流转。 - 如果有下一个状态,就递归触发 handleEvent() ,直到完成整个订单生命周期。
1️⃣ 订单事件枚举
java
public enum OrderEvent {
PAY, // 支付
SHIP, // 发货
DELIVER, // 收货
COMPLETE // 完成订单
}
每个 OrderState
执行完 Handler
后,发送 OrderEvent
,由事件决定下一个状态。
2️⃣ 订单状态枚举
java
import java.util.HashMap;
import java.util.Map;
public enum OrderState {
NEW(NewOrderHandler.class, OrderEvent.PAY), //待支付 -> 支付事件
PAID(PaidOrderHandler.class, OrderEvent.SHIP), //已支付 -> 发货事件
SHIPPED(ShippedOrderHandler.class, OrderEvent.DELIVER), // 已发货 -> 收货事件
DELIVERED(DeliveredOrderHandler.class, OrderEvent.COMPLETE), //已收货 -> 完成
COMPLETED(CompletedOrderHandler.class, null); // 终态
private final Class<? extends OrderStateHandler> handlerClass;
private final OrderEvent event;
// 事件 -> 下一个状态 映射
private static final Map<OrderEvent, OrderState> eventToNextState = new HashMap<>();
static {
OrderState[] states = values();
for (int i = 0; i < states.length - 1; i++) { // 遍历除终态外的所有状态
eventToNextState.put(states[i].event, states[i + 1]);
}
}
OrderState(Class<? extends OrderStateHandler> handlerClass, OrderEvent event) {
this.handlerClass = handlerClass;
this.event = event;
}
public OrderStateHandler getHandler() {
try {
return handlerClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("状态处理类实例化失败:" + handlerClass.getSimpleName(), e);
}
}
public static OrderState getNextState(OrderEvent event) {
return eventToNextState.get(event);
}
}
3️⃣ 订单状态处理接口
java
public interface OrderStateHandler {
void handle();
}
4️⃣ 具体的状态处理类
java
public class NewOrderHandler implements OrderStateHandler {
public void handle() {
System.out.println("订单已创建,等待支付...");
}
}
public class PaidOrderHandler implements OrderStateHandler {
public void handle() {
System.out.println("订单已支付,准备发货...");
}
}
public class ShippedOrderHandler implements OrderStateHandler {
public void handle() {
System.out.println("订单已发货,等待签收...");
}
}
public class DeliveredOrderHandler implements OrderStateHandler {
public void handle() {
System.out.println("订单已签收,交易完成!");
}
}
public class CompletedOrderHandler implements OrderStateHandler {
public void handle() {
System.out.println("订单已完成,流程结束!");
}
}
5️⃣ 订单状态机
java
public class OrderStateMachine {
private OrderState currentState;
public OrderStateMachine() {
this.currentState = OrderState.NEW; // 初始状态
}
//事件自动流转
public void handleEvent(OrderEvent event) {
OrderState nextState = OrderState.getNextState(event);
if (nextState == null) {
System.out.println("当前状态 " + currentState + " 不支持事件:" + event);
return;
}
System.out.println("状态切换到:" + nextState);
nextState.getHandler().handle();
this.currentState = nextState;
// 继续触发下一个状态
if (this.currentState != OrderState.COMPLETED && this.currentState.event != null) {
handleEvent(this.currentState.event);
}
}
}
6️⃣ 测试代码
java
public class StateMachineTest {
public static void main(String[] args) {
OrderStateMachine orderStateMachine = new OrderStateMachine();
orderStateMachine.handleEvent(OrderEvent.PAY);
}
}
✅ 运行结果
erlang
复制编辑
状态切换到:PAID
订单已支付,准备发货...
状态切换到:SHIPPED
订单已发货,等待签收...
状态切换到:DELIVERED
订单已签收,交易完成!
状态切换到:COMPLETED
订单已完成,流程结束!
异步回调处理
新增一个 支付回调监听器,用来处理第三方支付平台的异步通知:
根据回调信息找到单号 -> 单子状态 -> 状态映射事件 ->handleEvent继续执行。
java
public class PaymentCallbackListener {
private final OrderStateMachine orderStateMachine;
public PaymentCallbackListener(OrderStateMachine orderStateMachine) {
this.orderStateMachine = orderStateMachine;
}
public void onPaymentSuccess(String orderId) {
System.out.println("收到支付成功回调,订单ID:" + orderId);
// 触发订单状态流转(支付成功)
orderStateMachine.handleEvent(OrderEvent.PAY);
}
}
🎯 方案亮点
优化点 | 设计方案 |
---|---|
自动状态流转 | 只需调用 handleEvent(OrderEvent.PAY) ,后续状态自动执行 |
责任链模式 | handleEvent() 递归执行,确保状态流转 |
策略模式 | OrderStateHandler 让每个状态的业务逻辑独立 |
枚举映射优化 | eventToNextState 确保事件映射到正确的下一个状态 |
避免硬编码 | getHandler() 反射实例化,减少 if-else 判断 |
🚀 总结
✅ 这个方案实现了一个完整的状态机框架,具备自动状态流转、清晰的业务分离,并避免了 Map 关联映射的额外复杂性。
✨ 核心思路:
- 用枚举存储状态和事件关系 ,确保状态流转的正确性。
- 策略模式封装不同状态的处理逻辑 ,避免
if-else
代码膨胀。 - 责任链模式自动推进事件 ,只需触发
PAY
,即可完成整个流程。 - 支持扩展 :只需在
OrderState
中新增状态,就能支持新的业务需求!
这样设计,可读性强、扩展性高、易维护! 💡