状态模式 (State Pattern)

文章目录

状态模式 (State Pattern)

状态模式 是一种 行为型设计模式,允许对象在其内部状态改变时改变其行为,使得对象看起来像是改变了其类。


原理

  1. 核心思想 :
    • 将与对象状态相关的行为抽象到独立的状态类中。
    • 通过在不同状态下切换状态类,改变对象的行为。
  2. 适用场景 :
    • 对象的行为随状态的改变而改变。
    • 状态的条件逻辑复杂,使用模式可以避免复杂的 if-else 或 switch-case。
  3. 参与角色 :
    • Context(上下文类) :
      • 管理状态,并向客户端提供统一的接口。
      • 内部维护一个当前状态实例。
    • State(状态接口) :
      • 定义具体状态的行为接口。
    • ConcreteState(具体状态类) :
      • 实现状态接口,定义特定状态的行为。

优点

  1. 消除条件逻辑 :
    • 通过多态分离状态行为,避免复杂的条件判断语句。
  2. 增加扩展性 :
    • 增加新状态无需修改已有代码,符合 开闭原则。
  3. 状态自包含 :
    • 每个状态独立,易于管理。

缺点

  1. 增加类数量 :
    • 每种状态都需要一个类,导致类的数量增加。
  2. 状态切换复杂性 :
    • 如果状态间切换规则复杂,可能使上下文类难以管理。

示例代码

场景描述

模拟一个订单系统,订单可以处于不同状态(新建、支付、发货、完成)。不同状态下的行为有所不同。


1. 定义状态接口
java 复制代码
// 状态接口
public interface OrderState {
    void handle(OrderContext context);
}

2. 定义具体状态类
java 复制代码
// 新建状态
public class NewState implements OrderState {
    @Override
    public void handle(OrderContext context) {
        System.out.println("Order is in 'New' state.");
        context.setState(new PaidState());
    }
}

// 支付状态
public class PaidState implements OrderState {
    @Override
    public void handle(OrderContext context) {
        System.out.println("Order is in 'Paid' state.");
        context.setState(new ShippedState());
    }
}

// 发货状态
public class ShippedState implements OrderState {
    @Override
    public void handle(OrderContext context) {
        System.out.println("Order is in 'Shipped' state.");
        context.setState(new CompletedState());
    }
}

// 完成状态
public class CompletedState implements OrderState {
    @Override
    public void handle(OrderContext context) {
        System.out.println("Order is in 'Completed' state.");
        // 最终状态,无法再改变
    }
}

3. 定义上下文类
java 复制代码
// 上下文类
public class OrderContext {
    private OrderState state;

    public OrderContext() {
        // 初始状态为新建
        this.state = new NewState();
    }

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

    public void processOrder() {
        state.handle(this);
    }
}

4. 客户端代码
java 复制代码
public class StatePatternExample {
    public static void main(String[] args) {
        OrderContext order = new OrderContext();

        // 流程处理
        order.processOrder(); // 新建 -> 支付
        order.processOrder(); // 支付 -> 发货
        order.processOrder(); // 发货 -> 完成
        order.processOrder(); // 完成状态,无进一步操作
    }
}

输出结果
text 复制代码
Order is in 'New' state.
Order is in 'Paid' state.
Order is in 'Shipped' state.
Order is in 'Completed' state.

UML 类图

复制代码
        +-----------------+
        |    OrderState   |
        +-----------------+
        | + handle(Context)|
        +-----------------+
               ^
               |
        +------+-------+--------------------+-------------------+
        |              |                    |                   |
  +-------------+ +-------------+    +-------------+     +-------------+
  |  NewState   | |  PaidState  |    | ShippedState|     |CompletedState|
  +-------------+ +-------------+    +-------------+     +-------------+
  | + handle()  | | + handle()  |    | + handle()  |     | + handle()  |
  +-------------+ +-------------+    +-------------+     +-------------+
               ^
               |
        +----------------------+
        |     OrderContext     |
        +----------------------+
        | - state : OrderState |
        | + setState(state)    |
        | + processOrder()     |
        +----------------------+

使用场景

  1. 状态转换系统 :
    • 订单、流程审批等具有状态转换逻辑的系统。
  2. 游戏开发 :
    • 玩家角色的状态切换(如站立、行走、跳跃等)。
  3. 工作流引擎 :
    • 工单的状态流转(如创建、处理中、已完成)。

扩展与优化

  1. 状态复用 :
    • 如果某些状态是无状态的,可以用单例模式实现。
  2. 状态机框架 :
    • 对于复杂状态切换,可以使用现成的状态机框架(如 Spring Statemachine)。
  3. 状态数据分离 :
    • 将状态行为与具体状态数据分离,适用于复杂业务逻辑。

小结

  • 状态模式将状态与行为解耦,避免了复杂的条件逻辑。
  • 适用于对象行为随状态变化的场景。
  • 实现上要平衡状态类数量与复杂性的关系,防止类爆炸。
相关推荐
火云代理11 小时前
同一个网站,有的网络能打开、有的打不开?认识 IPv4 与 IPv6 的访问差异
服务器·网络·网络协议·tcp/ip·测试工具·php·状态模式
FungLeo3 天前
成为全栈·Vue 管理后台篇·分页只显示第一页:从接口total 定位到前端修复
前端·vue.js·状态模式·分页·naive ui·服务端分页·前端问题排查
严肃小白兔5 天前
TanStack Router 更新构建工具链:Node.js 兼容性、路由分割与前端工程实践
前端·node.js·状态模式
大江东去浪淘尽千古风流人物14 天前
【HexVIO】DSP卸载双目惯性VIO:Hexagon向量化前端与单帧融合调度深度解析
前端·状态模式·slam·dsp·vio·hexagon·移动端加速
吃一碗粉只付一碗钱14 天前
12-给SPA友好的401和403响应
c#·状态模式
sunlifenger15 天前
嵌入式部署,解锁张家港智慧灯杆的“极简组网”密码
科技·状态模式
上火的金鱼妹16 天前
关于多进程sse连接通知的实战
javascript·状态模式·sse
阿俊-全栈开发16 天前
LikeShop 小程序商城首页可配置弹窗的设计与实现(Java + uni-app)
小程序·状态模式·likeshop·likeshop开源商城
lingyubb16 天前
配音工具怎么选?从 TTS 合成链路看 6 个可量化参数
状态模式