一文搞懂开放封闭原则

开放封闭原则(Open-Closed Principle, OCP)是面向对象设计(Object-Oriented Design)的基本原则之一,最早由 Bertrand Meyer 在其1988年的著作《Object-Oriented Software Construction》中提出。该原则的主要内容如下:

开放封闭原则定义

开放封闭原则表明:

软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需求发生变化时,我们应该能够在不修改原有代码的基础上,通过新增代码的方式来满足新的需求。

主要要点

  1. 扩展性: 软件实体应该容易扩展,以便在不触及原有结构和功能的基础上增加新的功能。设计时应预见到未来可能的变化,并创建抽象层和扩展点,使新功能可以通过扩展这些点来实现。
  2. 稳定性: 已经部署并经过验证的软件实体(尤其是稳定的底层组件和基础架构)应该尽可能避免修改。频繁修改既有的代码不仅增加了出错的风险,还可能引发连锁反应,影响到依赖于该代码的其他部分。

实现方式

  • 抽象类与接口:定义抽象类或接口来描述共同行为,然后通过创建新的派生类或实现接口来增加功能,而不是修改原有类。
  • 策略模式:定义一组算法族,分别封装在不同的类中,使得它们之间可以互相替换。策略模式允许算法独立于使用它的客户代码变化。
  • 装饰者模式:动态地给对象添加职责,提供了比继承更为灵活的替代方案,允许在运行时改变对象的行为。
  • 工厂方法模式:创建对象的接口,但让子类决定实例化哪一个类。这样,系统就能在不修改自身的情况下扩展产品类系列。

示例说明

下面我将以JavaScript为例,展示如何运用开放封闭原则(OCP)设计一个简单的计费系统。假设我们开始时有一个处理普通订单的计费服务,之后又需要支持VIP用户的折扣计费。

初始版本:普通订单计费服务
// 假设有一个基础的订单类
class Order {
  constructor(totalPrice) {
    this.totalPrice = totalPrice;
  }
}

// 普通订单计费服务
class BillingService {
  calculateOrderCost(order) {
    if (!(order instanceof Order)) {
      throw new Error('Invalid order');
    }
    
    return order.totalPrice;
  }
}

// 创建一个普通订单
const regularOrder = new Order(100);

// 创建并使用计费服务
const billing = new BillingService();
console.log(billing.calculateOrderCost(regularOrder)); // 输出:100
扩展版本:支持VIP订单
// 新增VIP订单类,它继承自Order
class VIPOrder extends Order {
  constructor(totalPrice, vipDiscount) {
    super(totalPrice);
    this.vipDiscount = vipDiscount;
  }

  applyVipDiscount() {
    return this.totalPrice * (1 - this.vipDiscount);
  }
}

// 创建一个VIP订单计费策略类,遵循策略模式
class VipBillingStrategy {
  calculateOrderCost(order) {
    if (order instanceof VIPOrder) {
      return order.applyVipDiscount();
    } else {
      throw new Error('This is not a VIP order');
    }
  }
}

// 修改BillingService,使其支持不同的计费策略
class BillingService {
  constructor(strategy = new DefaultBillingStrategy()) {
    this.strategy = strategy;
  }

  setStrategy(strategy) {
    this.strategy = strategy;
  }

  calculateOrderCost(order) {
    return this.strategy.calculateOrderCost(order);
  }
}

// 创建一个默认计费策略,用于处理普通订单
class DefaultBillingStrategy {
  calculateOrderCost(order) {
    if (order instanceof Order) {
      return order.totalPrice;
    } else {
      throw new Error('Invalid order');
    }
  }
}

// 使用VIP订单并切换计费策略
const vipOrder = new VIPOrder(200, 0.2); // 假设VIP有20%的折扣

const billing = new BillingService(new DefaultBillingStrategy());
billing.setStrategy(new VipBillingStrategy());

console.log(billing.calculateOrderCost(vipOrder)); // 输出:160

// 对于普通订单,仍然可以使用同样的计费服务
console.log(billing.calculateOrderCost(regularOrder)); // 输出:100

在这个例子中,我们遵循开放封闭原则:

  • 对扩展开放:我们通过创建VIPOrder类以及VipBillingStrategy类,对VIP订单的处理进行了扩展,没有修改原有的Order类或BillingService的基础功能。
  • 对修改封闭:原有的Order类和最初版本的BillingService在面对新的需求时没有被直接修改,而是通过添加新的类和策略来实现功能扩展。

为何重要

遵循开放封闭原则有助于:

  • 提高复用性:已经测试过的、稳定的代码更容易重复利用。
  • 降低耦合度:减少各个模块之间的相互依赖,使得系统更具灵活性。
  • 维护性提升:变更时只需关注新增代码,大大降低了潜在的bug引入风险。
  • 遵循开闭原则是实现软件系统持续演进的关键手段,它使得系统能够应对不断变化的需求,同时保持系统整体的稳定和可控性。
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值