理解开闭原则:求非平凡Java类反例
违反开闭原则的Java示例及分析
反例代码:硬编码支付逻辑的订单处理器
假设我们有一个处理订单支付的类,它直接把所有支付方式的逻辑写在了同一个方法里:
public class OrderProcessor { public void processPayment(Order order, String paymentType) { if ("ALIPAY".equals(paymentType)) { // 支付宝支付逻辑:调用支付宝SDK、验证签名、处理回调等 System.out.println("处理支付宝支付:订单号" + order.getId()); // 省略具体实现细节 } else if ("WECHAT".equals(paymentType)) { // 微信支付逻辑:调用微信支付API、生成预支付单等 System.out.println("处理微信支付:订单号" + order.getId()); // 省略具体实现细节 } // 新增支付方式时,必须在这里加新的else if分支 } } class Order { private String id; public Order(String id) { this.id = id; } public String getId() { return id; } }
违反开闭原则的原因
开闭原则要求软件实体(类、模块、函数等)对扩展开放,对修改关闭。这个OrderProcessor类完全违反了这一点:
- 新增支付方式(比如银联支付、Apple Pay)时,必须直接修改
processPayment方法的代码,添加新的条件分支 - 它没有提供任何扩展点,所有支付逻辑都耦合在同一个类中,无法通过新增类来扩展功能
具体弊端
- 回归风险高:修改原有方法时,可能误破坏已有支付方式的逻辑,比如改坏支付宝的签名验证规则,导致线上支付故障。每次新增功能都要重新测试所有已有支付方式,测试成本陡增。
- 违反单一职责:
OrderProcessor既负责订单支付的流程控制,又要实现每种支付方式的具体逻辑,职责混杂,代码臃肿,后期维护难度极大。 - 耦合度极高:支付方式的变化直接绑定到
OrderProcessor的代码,一旦某个支付方式的API更新,必须修改这个核心类,牵一发而动全身。 - 扩展性差:如果要支持10种支付方式,
processPayment方法会变成一个巨型条件判断块,可读性和可维护性完全丧失。
符合开闭原则的改进方案
通过策略模式重构,抽象出支付处理的接口,让每种支付方式成为独立的实现类:
// 抽象支付处理器接口(扩展点) public interface PaymentProcessor { void process(Order order); } // 支付宝支付实现 public class AlipayProcessor implements PaymentProcessor { @Override public void process(Order order) { System.out.println("处理支付宝支付:订单号" + order.getId()); // 具体支付宝逻辑 } } // 微信支付实现 public class WechatProcessor implements PaymentProcessor { @Override public void process(Order order) { System.out.println("处理微信支付:订单号" + order.getId()); // 具体微信逻辑 } } // 订单处理器依赖抽象接口,无需修改即可扩展 public class OrderProcessor { private PaymentProcessor paymentProcessor; public OrderProcessor(PaymentProcessor paymentProcessor) { this.paymentProcessor = paymentProcessor; } public void processPayment(Order order) { paymentProcessor.process(order); } }
重构后,新增银联支付只需要创建UnionPayProcessor implements PaymentProcessor,完全不需要修改OrderProcessor的代码,真正做到了对扩展开放,对修改关闭。
内容的提问来源于stack exchange,提问作者djna
相关产品推荐
相关产品推荐

