商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 如何在 Java 中利用 状态模式 消除类中复杂的 if-else 逻辑并实现状态行为封装

如何在 Java 中利用 状态模式 消除类中复杂的 if-else 逻辑并实现状态行为封装

  发布于2026-07-08 阅读(0)

扫一扫,手机访问

代码里一旦出现大量 if-else 或 switch-case 来判断对象状态、执行不同行为,维护成本就开始悄悄攀升了。更头疼的是,每次新增一个状态,都得去翻遍所有条件分支——改漏一个就是线上事故。有没有一种设计,能让状态变化本身决定该做什么,彻底跟那些冗长的条件判断说再见?状态模式就是干这个的。

如何在 Ja va 中 利用 状态模式 消除类中复杂的 if-else 逻辑并实现状态行为封装

状态模式的核心思想

一句话概括:把对象在不同状态下的行为封装成独立的类,对象内部状态发生变化时,其行为也随之自动切换。不是用 if-else 去“看”当前状态再决定做什么,而是直接让“状态本身”来决定——对象只管把请求委托给当前状态实例,行为与条件判断彻底解耦。

典型 if-else 场景与问题

拿订单来举例再合适不过。一个订单对象通常有“待支付”“已支付”“已发货”“已完成”“已取消”等状态,每个操作(支付、发货、退款)都要先检查当前状态是否允许,再执行动作,最后更新状态。硬编码的结果就是:方法里塞满嵌套或并列的 if-else,看着就头疼。

这种写法的痛点很明显:

  • 订单类膨胀到不行,既要管业务逻辑又要管状态流转,职责不单一
  • 状态校验和行为逻辑混在一起,读代码就像在猜谜
  • 加一个新状态(比如“部分发货”),所有涉及状态判断的方法都得改一遍
  • 状态之间非法转移根本防不住——比如从“已完成”又跑去“支付”

用状态模式重构的关键步骤

以订单为例,落地只要四步,非常清爽:

  • 定义状态接口:声明所有状态共有的行为方法,比如 pay()ship()cancel()
  • 为每种状态实现具体类:每个类只专注自己状态下的合法行为。例如 PaidState 实现 ship()(允许发货),但 pay() 直接抛异常或忽略
  • 订单持有状态引用:用组合代替继承,订单持有一个 OrderState 接口引用,初始设为 CreatedState
  • 状态切换由状态自身控制:比如 CreatedState.pay() 执行成功后,主动把订单的状态引用设为 new PaidState(order)

这样一来,订单的 pay() 方法就简化为一行:currentState.pay(),零 if-else。

实际代码片段示意

先看状态接口:

interface OrderState {
    void pay(Order order);
    void ship(Order order);
    void cancel(Order order);
}

具体状态之一——已支付状态:

class PaidState implements OrderState {
    @Override
    public void pay(Order order) {
        throw new IllegalStateException("Already paid");
    }
    @Override
    public void ship(Order order) {
        System.out.println("Shipping...");
        order.setState(new ShippedState(order)); // 自行切换状态
    }
    @Override
    public void cancel(Order order) {
        System.out.println("Cancelling paid order...");
        order.setState(new CancelledState(order));
    }
}

订单类(精简版):

class Order {
    private OrderState state;
    public Order() {
        this.state = new CreatedState(this);
    }
    public void pay() { state.pay(this); }
    public void ship() { state.ship(this); }
    public void cancel() { state.cancel(this); }
    public void setState(OrderState state) { this.state = state; }
}

需要留意的是:状态类可以持有对上下文(Order)的引用,用于读取数据或触发状态变更,但要避免循环依赖。

本文转载于:https://www.php.cn/faq/2420547.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注