Skip to content
Method约 1 分钟0 个小节更新于 2026/06/19在线编辑

状态模式

状态模式用于把对象在不同状态下的行为封装到不同状态类中,让对象状态变化时行为也随之变化。

一句话理解:状态不同,行为不同,就把状态拆成类。

解决什么问题

订单有多个状态:

text
待支付 -> 已支付 -> 已发货 -> 已完成
待支付 -> 已取消

如果所有状态判断都写在一个类里:

java
if ("WAIT_PAY".equals(status)) {
    // pay
} else if ("PAID".equals(status)) {
    // ship
} else if ("SHIPPED".equals(status)) {
    // finish
}

随着状态和动作增加,判断会越来越复杂。状态模式把不同状态下的行为拆出去。

基本结构

text
Context -> State
State   -> handle(context)

角色:

  • Context:上下文对象,持有当前状态。
  • State:状态接口。
  • ConcreteState:具体状态,定义该状态下的行为和状态流转。

Java 示例

状态接口:

java
interface OrderState {
    void pay(OrderContext context);

    void ship(OrderContext context);

    String name();
}

上下文:

java
class OrderContext {
    private OrderState state;

    OrderContext(OrderState state) {
        this.state = state;
    }

    public void setState(OrderState state) {
        this.state = state;
    }

    public void pay() {
        state.pay(this);
    }

    public void ship() {
        state.ship(this);
    }

    public String stateName() {
        return state.name();
    }
}

待支付状态:

java
class WaitPayState implements OrderState {
    public void pay(OrderContext context) {
        System.out.println("pay success");
        context.setState(new PaidState());
    }

    public void ship(OrderContext context) {
        throw new IllegalStateException("order is not paid");
    }

    public String name() {
        return "WAIT_PAY";
    }
}

已支付状态:

java
class PaidState implements OrderState {
    public void pay(OrderContext context) {
        throw new IllegalStateException("order already paid");
    }

    public void ship(OrderContext context) {
        System.out.println("ship success");
        context.setState(new ShippedState());
    }

    public String name() {
        return "PAID";
    }
}

class ShippedState implements OrderState {
    public void pay(OrderContext context) {
        throw new IllegalStateException("order already shipped");
    }

    public void ship(OrderContext context) {
        throw new IllegalStateException("order already shipped");
    }

    public String name() {
        return "SHIPPED";
    }
}

使用:

java
OrderContext order = new OrderContext(new WaitPayState());
order.pay();
order.ship();
System.out.println(order.stateName());

使用场景

  • 订单状态流转。
  • 工单流程。
  • 账号状态。
  • TCP 连接状态。
  • 工作流节点。
  • 状态机。

优点

  • 消除大量状态判断。
  • 每个状态职责清晰。
  • 状态流转逻辑更集中。
  • 新增状态相对独立。

缺点

  • 状态类数量增加。
  • 状态流转分散在状态类中,整体流程需要额外文档或图辅助。
  • 状态很多且规则复杂时,需要考虑状态机框架。

和策略模式的区别

模式重点
状态对象内部状态变化导致行为变化
策略外部选择不同算法执行

状态模式通常会改变上下文状态;策略模式通常只是替换算法,不负责状态流转。

实战注意

订单、支付、审批这类严肃状态流转,最好配合状态枚举、数据库状态字段、状态流转表和幂等控制一起设计。

以工程实践沉淀知识,以文档复盘成长。