一、Cola 状态机是什么?
Cola 状态机(Cola State Machine)是阿里开源的一款轻量级、易用的状态机框架,核心用于管理对象的状态转换逻辑,能帮你把复杂的状态流转规则从业务代码中抽离出来,让状态转换逻辑更清晰、可维护。
它的核心概念:
- State(状态):对象当前所处的状态(比如订单的「待支付」「已支付」「已取消」);
- Event(事件):触发状态转换的动作(比如订单的「支付」「取消」「退款」);
- Transition(转换):从一个状态通过某个事件转换到另一个状态的规则;
- Context(上下文):状态转换时传递的附加数据(比如订单ID、操作人);
- Action(动作):状态转换过程中执行的自定义逻辑(比如状态变更后记录日志)。
二、Java 示例:订单状态流转
下面以「订单状态管理」为例,实现从「待支付」→「已支付」→「已发货」→「已完成」,以及「待支付」→「已取消」的流转逻辑。
1. 前置准备:引入依赖
首先在 Maven 项目的 pom.xml 中添加 Cola 状态机依赖:
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-statemachine</artifactId>
<version>4.3.1</version> <!-- 使用最新稳定版 -->
</dependency>
2. 完整代码示例
import com.alibaba.cola.statemachine.Action;
import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.StateMachineFactory;
import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
/**
* Cola 状态机示例:订单状态流转
*/
public class OrderStateMachineDemo {
// 1. 定义订单状态(State)
enum OrderState {
WAIT_PAYMENT, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
COMPLETED, // 已完成
CANCELLED // 已取消
}
// 2. 定义触发事件(Event)
enum OrderEvent {
PAY, // 支付
SHIP, // 发货
FINISH, // 完成
CANCEL // 取消
}
// 3. 定义状态转换时的上下文(携带订单信息)
static class OrderContext {
private String orderId; // 订单ID
private String operator; // 操作人
public OrderContext(String orderId, String operator) {
this.orderId = orderId;
this.operator = operator;
}
// getter/setter
public String getOrderId() { return orderId; }
public String getOperator() { return operator; }
}
public static void main(String[] args) {
// 4. 构建状态机
StateMachineBuilder<OrderState, OrderEvent, OrderContext> builder =
StateMachineBuilderFactory.create();
// 5. 配置状态转换规则
// 规则1:待支付 → 已支付(触发事件:支付),并执行支付成功的动作
builder.externalTransition()
.from(OrderState.WAIT_PAYMENT)
.to(OrderState.PAID)
.on(OrderEvent.PAY)
.when(checkOrderExist()) // 条件:订单存在(可选)
.perform(paySuccessAction()); // 执行自定义动作
// 规则2:已支付 → 已发货(触发事件:发货)
builder.externalTransition()
.from(OrderState.PAID)
.to(OrderState.SHIPPED)
.on(OrderEvent.SHIP)
.perform(shipAction());
// 规则3:已发货 → 已完成(触发事件:完成)
builder.externalTransition()
.from(OrderState.SHIPPED)
.to(OrderState.COMPLETED)
.on(OrderEvent.FINISH)
.perform(finishAction());
// 规则4:待支付 → 已取消(触发事件:取消)
builder.externalTransition()
.from(OrderState.WAIT_PAYMENT)
.to(OrderState.CANCELLED)
.on(OrderEvent.CANCEL)
.perform(cancelAction());
// 6. 构建并获取状态机实例
StateMachine<OrderState, OrderEvent, OrderContext> stateMachine =
builder.build("order-state-machine");
// 7. 测试状态转换
OrderContext context = new OrderContext("ORDER_001", "用户张三");
// 测试1:待支付 → 已支付
OrderState newState1 = stateMachine.fireEvent(OrderState.WAIT_PAYMENT, OrderEvent.PAY, context);
System.out.println("当前订单状态:" + newState1); // 输出:PAID
// 测试2:已支付 → 已发货
OrderState newState2 = stateMachine.fireEvent(newState1, OrderEvent.SHIP, context);
System.out.println("当前订单状态:" + newState2); // 输出:SHIPPED
// 测试3:已发货 → 已完成
OrderState newState3 = stateMachine.fireEvent(newState2, OrderEvent.FINISH, context);
System.out.println("当前订单状态:" + newState3); // 输出:COMPLETED
// 测试4:待支付 → 已取消(新建一个待支付订单)
OrderContext cancelContext = new OrderContext("ORDER_002", "用户李四");
OrderState newState4 = stateMachine.fireEvent(OrderState.WAIT_PAYMENT, OrderEvent.CANCEL, cancelContext);
System.out.println("当前订单状态:" + newState4); // 输出:CANCELLED
}
// ---------------------- 自定义动作/条件 ----------------------
// 条件:检查订单是否存在(返回true则允许转换)
private static java.util.function.Predicate<OrderContext> checkOrderExist() {
return context -> {
System.out.println("检查订单[" + context.getOrderId() + "]是否存在:存在");
return true;
};
}
// 动作:支付成功后的逻辑(比如记录日志、扣减库存)
private static Action<OrderState, OrderEvent, OrderContext> paySuccessAction() {
return (from, to, event, context) -> {
System.out.println("订单[" + context.getOrderId() + "]由" + from + "→" + to
+ ",操作人:" + context.getOperator() + ",执行支付成功逻辑(扣库存、生成支付单)");
};
}
// 动作:发货逻辑
private static Action<OrderState, OrderEvent, OrderContext> shipAction() {
return (from, to, event, context) -> {
System.out.println("订单[" + context.getOrderId() + "]发货,操作人:" + context.getOperator());
};
}
// 动作:完成订单逻辑
private static Action<OrderState, OrderEvent, OrderContext> finishAction() {
return (from, to, event, context) -> {
System.out.println("订单[" + context.getOrderId() + "]完成,操作人:" + context.getOperator());
};
}
// 动作:取消订单逻辑
private static Action<OrderState, OrderEvent, OrderContext> cancelAction() {
return (from, to, event, context) -> {
System.out.println("订单[" + context.getOrderId() + "]取消,操作人:" + context.getOperator());
};
}
}
3. 代码关键部分解释
- 状态/事件定义:用枚举
OrderState和OrderEvent明确订单的所有状态和触发事件,符合「枚举约束状态」的最佳实践; - 上下文(OrderContext):传递状态转换时的附加数据(订单ID、操作人),避免硬编码;
- 状态机构建:通过
StateMachineBuilder配置「从状态→到状态→触发事件→条件→动作」的完整规则;externalTransition():表示「外部转换」(跨状态转换,最常用);when():可选,配置状态转换的前置条件(返回true才允许转换);perform():配置状态转换时执行的自定义业务逻辑;
- 触发状态转换:通过
stateMachine.fireEvent(当前状态, 触发事件, 上下文)触发状态变更,返回新状态。
4. 运行结果
检查订单[ORDER_001]是否存在:存在
订单[ORDER_001]由WAIT_PAYMENT→PAID,操作人:用户张三,执行支付成功逻辑(扣库存、生成支付单)
当前订单状态:PAID
订单[ORDER_001]发货,操作人:用户张三
当前订单状态:SHIPPED
订单[ORDER_001]完成,操作人:用户张三
当前订单状态:COMPLETED
订单[ORDER_002]取消,操作人:用户李四
当前订单状态:CANCELLED
三、总结
- 核心价值:Cola 状态机将「状态转换规则」与「业务逻辑」解耦,避免大量
if-else判断,让状态流转更清晰、易维护; - 核心用法:定义状态/事件 → 构建状态机并配置转换规则(含条件/动作) → 调用
fireEvent触发状态转换; - 适用场景:订单状态、物流状态、审批流程、工单状态等需要明确状态流转的业务场景。
补充说明
- 如果触发不合法的状态转换(比如「已支付」触发「取消」事件),框架会抛出
StateMachineException,可通过异常处理保障逻辑严谨性;
注意:本文归作者所有,未经作者允许,不得转载