状态设计模式如何满足开闭设计原则?
状态设计模式如何满足开闭原则?
首先明确:开闭原则的核心是——软件实体要对扩展开放,对修改关闭。也就是说,新增功能时,优先通过添加新代码实现,而非改动已有稳定代码。
状态模式的设计思路恰好完美契合这一点:它把对象的每个状态都封装成独立的类,对象的行为完全由当前状态类来处理,主对象只负责持有当前状态并委托行为。
反例:不用状态模式的糟糕实现(违反开闭)
比如一个订单系统,不用状态模式的话,通常会写出一堆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类里的多个方法,完全违反开闭原则——每次扩展都要动原有代码,风险极高。
状态模式的实现(符合开闭)
用状态模式重构后,结构清晰且满足开闭:
- 定义状态行为接口
public interface OrderState { void pay(Order order); void ship(Order order); void refund(Order order); // 提前定义好所有可能的行为 }
- 实现具体状态类
// 创建状态 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("订单已退款,状态切换为已退款"); } } // 已发货、已完成状态类似,这里省略
- 订单类(主对象)
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
相关产品推荐
相关产品推荐

