Java 状态机(State Machine)模式

76 阅读2分钟

🧭 一、什么是状态机(State Machine)

状态机(State Machine)是一种非常常见的设计模式,
它通过**状态(State)事件(Event)**的组合来驱动程序的执行逻辑。

在状态机中,一个对象在任意时刻都处于某个“状态”,
当触发特定的“事件”后,它会**迁移(Transition)**到另一个状态,并执行对应的逻辑。


⚙️ 二、核心思想

状态机由三个核心要素组成:

要素说明
State(状态)当前对象的状态,如 PENDINGPAIDSHIPPED
Event(事件)导致状态转换的触发事件,如 PAY_SUCCESSSHIP
Transition(状态迁移)从一个状态到另一个状态的转变过程,可附带逻辑操作

💡 三、完整案例:订单状态流转

下面是一个完整的可运行示例:
演示订单从 待支付 → 已支付 → 已发货 → 已完成 的过程。

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

// 定义状态
enum OrderState {
    PENDING,     // 待支付
    PAID,        // 已支付
    SHIPPED,     // 已发货
    COMPLETED,   // 已完成
    CANCELED     // 已取消
}

// 定义事件
enum OrderEvent {
    PAY_SUCCESS,
    SHIP,
    DELIVER,
    CANCEL
}

// 状态机类
class StateMachine<S, E> {
    private S currentState;
    private final Map<String, Transition<S, E>> transitions = new HashMap<>();

    // 定义状态转换结构
    static class Transition<S, E> {
        S from;
        E event;
        S to;
        Runnable action;

        Transition(S from, E event, S to, Runnable action) {
            this.from = from;
            this.event = event;
            this.to = to;
            this.action = action;
        }
    }

    public StateMachine(S initState) {
        this.currentState = initState;
    }

    // 添加状态迁移
    public void addTransition(S from, E event, S to, Runnable action) {
        transitions.put(key(from, event), new Transition<>(from, event, to, action));
    }

    // 触发事件
    public void trigger(E event) {
        String k = key(currentState, event);
        Transition<S, E> t = transitions.get(k);
        if (t == null) {
            System.out.println("⚠️ 无效的状态转换:" + currentState + " 不能触发事件 " + event);
            return;
        }

        System.out.println("➡️ 状态变化:" + currentState + " → " + t.to);
        t.action.run();
        currentState = t.to;
    }

    public S getCurrentState() {
        return currentState;
    }

    private String key(S s, E e) {
        return s.toString() + "_" + e.toString();
    }
}

public class OrderStateMachineDemo {
    public static void main(String[] args) {
        StateMachine<OrderState, OrderEvent> sm = new StateMachine<>(OrderState.PENDING);

        // 添加状态流转规则
        sm.addTransition(OrderState.PENDING, OrderEvent.PAY_SUCCESS, OrderState.PAID,
                () -> System.out.println("✅ 订单支付成功,准备发货"));
        sm.addTransition(OrderState.PAID, OrderEvent.SHIP, OrderState.SHIPPED,
                () -> System.out.println("🚚 订单已发货"));
        sm.addTransition(OrderState.SHIPPED, OrderEvent.DELIVER, OrderState.COMPLETED,
                () -> System.out.println("🎉 订单已完成"));
        sm.addTransition(OrderState.PENDING, OrderEvent.CANCEL, OrderState.CANCELED,
                () -> System.out.println("❌ 订单已取消"));

        // 流程执行
        System.out.println("初始状态:" + sm.getCurrentState());
        sm.trigger(OrderEvent.PAY_SUCCESS);
        sm.trigger(OrderEvent.SHIP);
        sm.trigger(OrderEvent.DELIVER);
        sm.trigger(OrderEvent.CANCEL); // 无效操作
        System.out.println("最终状态:" + sm.getCurrentState());
    }
}

🧩 四、运行结果

初始状态:PENDING
➡️ 状态变化:PENDING → PAID
✅ 订单支付成功,准备发货
➡️ 状态变化:PAID → SHIPPED
🚚 订单已发货
➡️ 状态变化:SHIPPED → COMPLETED
🎉 订单已完成
⚠️ 无效的状态转换:COMPLETED 不能触发事件 CANCEL
最终状态:COMPLETED

🧠 五、总结与扩展

优点:

  • 逻辑清晰:用“状态+事件”代替多层 if/else。
  • 可扩展性强:增加新状态只需添加规则,不破坏原有逻辑。
  • 便于维护:结构化定义状态迁移,易于调试。

💡 扩展方向:

  • 支持异步执行(如结合 CompletableFuture
  • 持久化状态(如在数据库中记录状态变化)
  • 与 Spring StateMachine 集成,支持复杂业务流转