You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

状态设计模式如何满足开闭设计原则?

状态设计模式如何满足开闭原则?

首先明确:开闭原则的核心是——软件实体要对扩展开放,对修改关闭。也就是说,新增功能时,优先通过添加新代码实现,而非改动已有稳定代码。

状态模式的设计思路恰好完美契合这一点:它把对象的每个状态都封装成独立的类,对象的行为完全由当前状态类来处理,主对象只负责持有当前状态并委托行为。

反例:不用状态模式的糟糕实现(违反开闭)

比如一个订单系统,不用状态模式的话,通常会写出一堆if-else判断:

public class Order {
    private String state; // "CREATED", "PAID", "SHIPPED", "COMPLETED"

    public void pay() {
        if ("CREATED".equals(state)) {
            state = "PAID";
            System.out.println("订单已支付");
        } else {
            throw new IllegalStateException("当前状态无法支付");
        }
    }

    public void ship() {
        if ("PAID".equals(state)) {
            state = "SHIPPED";
            System.out.println("订单已发货");
        } else {
            throw new IllegalStateException("当前状态无法发货");
        }
    }

    // 如果要新增"退款"状态,必须修改这里的pay、ship,还要加新的refund方法,全是改动
}

这种写法下,新增任何状态(比如"退款")都要修改Order类里的多个方法,完全违反开闭原则——每次扩展都要动原有代码,风险极高。

状态模式的实现(符合开闭)

用状态模式重构后,结构清晰且满足开闭:

  1. 定义状态行为接口
public interface OrderState {
    void pay(Order order);
    void ship(Order order);
    void refund(Order order); // 提前定义好所有可能的行为
}
  1. 实现具体状态类
// 创建状态
public class CreatedState implements OrderState {
    @Override
    public void pay(Order order) {
        order.setState(new PaidState());
        System.out.println("订单已支付,状态切换为已支付");
    }

    @Override
    public void ship(Order order) {
        throw new IllegalStateException("未支付订单无法发货");
    }

    @Override
    public void refund(Order order) {
        throw new IllegalStateException("未支付订单无需退款");
    }
}

// 支付状态
public class PaidState implements OrderState {
    @Override
    public void pay(Order order) {
        throw new IllegalStateException("订单已支付,无需重复支付");
    }

    @Override
    public void ship(Order order) {
        order.setState(new ShippedState());
        System.out.println("订单已发货,状态切换为已发货");
    }

    @Override
    public void refund(Order order) {
        order.setState(new RefundedState());
        System.out.println("订单已退款,状态切换为已退款");
    }
}

// 已发货、已完成状态类似,这里省略
  1. 订单类(主对象)
public class Order {
    private OrderState currentState;

    public Order() {
        this.currentState = new CreatedState(); // 默认初始状态
    }

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

    // 所有行为都委托给当前状态处理
    public void pay() {
        currentState.pay(this);
    }

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

    public void refund() {
        currentState.refund(this);
    }
}

为什么符合开闭原则?

如果现在需要新增一个RefundedState(退款状态),只需要新建一个类实现OrderState接口,实现该状态下的pay、ship、refund逻辑即可——完全不需要修改Order类和已有的CreatedState、PaidState等类。

扩展新状态时,只添加代码,不修改原有代码,完美遵循了开闭原则的要求。

内容的提问来源于stack exchange,提问作者Jenkins2000

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:40:39