IIWAB cola状态机 - IIWAB

cola状态机

IIWAB 1月前 ⋅ 39 阅读

一、Cola 状态机是什么?

Cola 状态机(Cola State Machine)是阿里开源的一款轻量级、易用的状态机框架,核心用于管理对象的状态转换逻辑,能帮你把复杂的状态流转规则从业务代码中抽离出来,让状态转换逻辑更清晰、可维护。

它的核心概念:

  1. State(状态):对象当前所处的状态(比如订单的「待支付」「已支付」「已取消」);
  2. Event(事件):触发状态转换的动作(比如订单的「支付」「取消」「退款」);
  3. Transition(转换):从一个状态通过某个事件转换到另一个状态的规则;
  4. Context(上下文):状态转换时传递的附加数据(比如订单ID、操作人);
  5. 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. 代码关键部分解释

  1. 状态/事件定义:用枚举 OrderStateOrderEvent 明确订单的所有状态和触发事件,符合「枚举约束状态」的最佳实践;
  2. 上下文(OrderContext):传递状态转换时的附加数据(订单ID、操作人),避免硬编码;
  3. 状态机构建:通过 StateMachineBuilder 配置「从状态→到状态→触发事件→条件→动作」的完整规则;
    • externalTransition():表示「外部转换」(跨状态转换,最常用);
    • when():可选,配置状态转换的前置条件(返回 true 才允许转换);
    • perform():配置状态转换时执行的自定义业务逻辑;
  4. 触发状态转换:通过 stateMachine.fireEvent(当前状态, 触发事件, 上下文) 触发状态变更,返回新状态。

4. 运行结果

检查订单[ORDER_001]是否存在:存在
订单[ORDER_001]由WAIT_PAYMENT→PAID,操作人:用户张三,执行支付成功逻辑(扣库存、生成支付单)
当前订单状态:PAID
订单[ORDER_001]发货,操作人:用户张三
当前订单状态:SHIPPED
订单[ORDER_001]完成,操作人:用户张三
当前订单状态:COMPLETED
订单[ORDER_002]取消,操作人:用户李四
当前订单状态:CANCELLED

三、总结

  1. 核心价值:Cola 状态机将「状态转换规则」与「业务逻辑」解耦,避免大量 if-else 判断,让状态流转更清晰、易维护;
  2. 核心用法:定义状态/事件 → 构建状态机并配置转换规则(含条件/动作) → 调用 fireEvent 触发状态转换;
  3. 适用场景:订单状态、物流状态、审批流程、工单状态等需要明确状态流转的业务场景。

补充说明

  • 如果触发不合法的状态转换(比如「已支付」触发「取消」事件),框架会抛出 StateMachineException,可通过异常处理保障逻辑严谨性;

全部评论: 0

    我有话说: