首页 > 编程语言 >程序员必知!开放封闭原则的实战应用与案例分析

程序员必知!开放封闭原则的实战应用与案例分析

时间:2023-12-21 11:32:13浏览次数:34  
标签:实战 原则 修改 必知 代码 封闭 public 程序员 order

开放封闭原则是面向对象设计中的重要原则之一,它要求软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭。这意味着当需要添加新功能时,不应该修改现有的代码,而是应该通过扩展来实现。这可以通过使用接口、抽象类和多态等机制来实现,从而使系统更加灵活和可扩展。

程序员必知!开放封闭原则的实战应用与案例分析 - 程序员古德

定义

开放封闭原则(Open Closed Principle,简称OCP)是面向开放封闭原则(Open Closed Principle,简称OCP)是面向对象设计中的一个重要原则,它由Bertrand Meyer于1988年提出。该原则主张软件实体(类、模块、函数等等)应该对扩展开放,对修改关闭,这意味着,当需要添加新功能时,我们应该尽量通过扩展已有的代码来实现,而不是修改原有的代码。

该原则的核心思想是,对于已经设计好的软件实体,应该在不修改其源代码的情况下,通过扩展来增加新的功能或行为。换句话说,我们应该尽可能地保持软件实体的稳定性和可靠性,而不是通过修改源代码来适应新的需求。在实现开放封闭原则时,需要注意以下几点:

  1. 对扩展开放:当需要添加新功能时,应该通过扩展现有的类或模块来实现,而不是修改现有的代码。这可以通过使用接口、抽象类和多态等机制来实现。
  2. 对修改关闭:当添加新功能时,不应该修改现有的代码。如果必须修改现有的代码,那么这种修改应该是有计划、有目的的,并且应该尽量避免对其他部分的代码产生影响。
  3. 抽象化设计:通过抽象化设计,可以将具体的实现细节隐藏在抽象接口之后,从而保护现有的代码不被修改。同时,抽象化设计也可以提高代码的可重用性和可维护性。
  4. 模块化设计:通过模块化设计,可以将系统划分为多个独立的模块,每个模块都有明确的职责和功能。这样可以降低系统的耦合度,提高系统的可维护性和可扩展性。

程序员必知!开放封闭原则的实战应用与案例分析 - 程序员古德

代码案例

假设我们正在开发一个电商系统,其中包括一个订单处理模块,该模块负责处理用户的订单,包括计算订单金额、生成订单号、发送订单确认邮件等功能。

首先,我们来看一个不符合开放封闭原则的设计,代码如下:


/**
 * @版权 Copyright by 程序员古德 <br>
 * @创建人 程序员古德 <br>
 * @创建时间 2023/12/15 16:37 <br>
 */

// 不符合开放封闭原则的设计  
  
public class OrderProcessor {  
    public void processOrder(Order order) {  
        // 计算订单金额  
        double amount = calculateOrderAmount(order);  
          
        // 生成订单号  
        String orderNumber = generateOrderNumber();  
          
        // 发送订单确认邮件  
        sendOrderConfirmationEmail(order, amount, orderNumber);  
          
        // 其他订单处理逻辑...  
    }  
      
    private double calculateOrderAmount(Order order) {  
        // 计算订单金额的逻辑  
        return 0.0;  
    }  
      
    private String generateOrderNumber() {  
        // 生成订单号的逻辑  
        return null;  
    }  
      
    private void sendOrderConfirmationEmail(Order order, double amount, String orderNumber) {  
        // 发送订单确认邮件的逻辑  
    }  
}

在上面的代码中,OrderProcessor类负责处理订单的全部逻辑,包括计算金额、生成订单号、发送确认邮件等。如果我们需要添加新的功能,比如添加优惠券处理逻辑,就需要修改OrderProcessor类的代码,这样不符合开放封闭原则,每次添加新功能都需要修改已有代码,会增加系统的维护成本,并且容易引入错误。

为了解决这个问题,我们可以使用开放封闭原则进行改进,我们可以将订单处理的不同功能抽象为不同的接口,比如OrderAmountCalculatorOrderNumberGeneratorOrderConfirmationEmailSender等。然后,我们可以实现这些接口来提供具体的功能实现,这样,当需要添加新功能时,只需要扩展相应的接口,而不需要修改已有的代码,下面是改进后的代码:


/**
 * @版权 Copyright by 程序员古德 <br>
 * @创建人 程序员古德 <br>
 * @创建时间 2023/12/15 16:37 <br>
 */

// 符合开放封闭原则的设计  
  
public interface OrderAmountCalculator {  
    double calculate(Order order);  
}  
  
public interface OrderNumberGenerator {  
    String generate();  
}  
  
public interface OrderConfirmationEmailSender {  
    void send(Order order, double amount, String orderNumber);  
}  
  
public class SimpleOrderAmountCalculator implements OrderAmountCalculator {  
    @Override  
    public double calculate(Order order) {  
        // 计算订单金额的逻辑  
        return 0.0;  
    }  
}  
  
public class SimpleOrderNumberGenerator implements OrderNumberGenerator {  
    @Override  
    public String generate() {  
        // 生成订单号的逻辑  
        return null;  
    }  
}  
  
public class SimpleOrderConfirmationEmailSender implements OrderConfirmationEmailSender {  
    @Override  
    public void send(Order order, double amount, String orderNumber) {  
        // 发送订单确认邮件的逻辑  
    }  
}  
  
public class OrderProcessor {  
    private OrderAmountCalculator orderAmountCalculator;  
    private OrderNumberGenerator orderNumberGenerator;  
    private OrderConfirmationEmailSender orderConfirmationEmailSender;  
      
    public OrderProcessor(OrderAmountCalculator orderAmountCalculator, OrderNumberGenerator orderNumberGenerator, OrderConfirmationEmailSender orderConfirmationEmailSender) {  
        this.orderAmountCalculator = orderAmountCalculator;  
        this.orderNumberGenerator = orderNumberGenerator;  
        this.orderConfirmationEmailSender = orderConfirmationEmailSender;  
    }  
      
    public void processOrder(Order order) {  
        double amount = orderAmountCalculator.calculate(order);  
        String orderNumber = orderNumberGenerator.generate();  
        orderConfirmationEmailSender.send(order, amount, orderNumber);  
        // 其他订单处理逻辑...  
    }  
}  

在上面的代码中,我们将订单处理的不同功能抽象为了不同的接口,并且提供了相应的实现类,这样,当需要添加新功能时,只需要扩展相应的接口,并提供一个新的实现类即可,比如,如果我们想要添加优惠券处理逻辑,可以创建一个实现了OrderAmountCalculator接口的CouponOrderAmountCalculator类,然后在创建OrderProcessor对象时传入这个新的实现类即可。这种方式符合开放封闭原则,可以在不修改已有代码的情况下扩展系统的功能。同时,由于使用了接口进行抽象,代码的可读性和可维护性也得到了提高,这种方式可以使我们的系统更加灵活和可扩展。

核心总结

程序员必知!开放封闭原则的实战应用与案例分析 - 程序员古德

开封封闭原则(Open-Closed Principle,OCP)是面向对象设计的五个基本原则之一,它指导我们设计模块时应尽量使其对扩展开放,对修改关闭,这意味着我们可以增加新的功能,而不需要改动已有的代码。

优点:一是提高软件的可维护性,因为修改原有代码可能会引入新的错误;二是有利于团队协作,每个人都可以在不干扰其他人的情况下添加新功能;三是有利于复用,因为每个类或模块只做一件事,所以更容易找到可以复用的代码。

缺点:一是过度设计,如果预设了过多的扩展点,可能导致代码过于复杂;二是可能增加系统的耦合度,因为为了满足开封封闭原则,可能需要引入一些抽象类或接口。

使用建议:在实际开发中,我们应该根据项目需求和规模来权衡是否严格遵循开封封闭原则。对于小型项目或者短期内不会频繁变动的项目,可能不需要过度设计。而对于大型项目或者需要长期维护的项目,遵守开封封闭原则则更为重要。同时,我们也应该注意避免过度设计和增加系统耦合度的问题,可以通过重构和优化代码结构来解决这些问题。

标签:实战,原则,修改,必知,代码,封闭,public,程序员,order
From: https://blog.51cto.com/bytegood/8920037

相关文章

  • 《业务安全实战演练》时效绕过测试10
    一、大多有利用的案例发生在验证码以及业务数据的时效范围上,在之前的总结也有人将12306的作为典型,故,单独分类。1、时间刷新缺陷12306网站的买票业务是每隔5s,票会刷新一次。但是这个时间确实在本地设置的间隔。于是,在控制台就可以将这个时间的关联变量重新设置成1s或者更小,这样刷......
  • 【业务安全实战演练】密码找回模块测试08
    一、验证码客户端回显测试典型场景:任意用户登录使用验证码的场景:人机验证:防止机器操作,爆破表单。唯一凭据:唯一性判断,任意账户登录。​找回密码测试中要注意验证码是否会回显在响应中,有些网站程序会选择将验证码回显在响应中,来判断用户输入的验证码是否和响应中的......
  • Apache Kyuubi 讲解与实战操作
    目录一、概述二、SparkKyuubi架构三、Hadoop基础环境安装1)hadoop下载部署包2)创建网络3)部署MySQL4)部署HadoopHive四、SparkKyuubi安装1)下载Kyuubi2)下载Spark32)配置Kyuubi(Spark3)3)启动Kyuubi4)测试使用五、ApacheKyuubiHA部署1)部署Zookeeper3)KyuubiHA配置4)启动服务......
  • 风控决策引擎——决策流构建实战
    引言本篇主要聚焦介绍风控决策引擎中决策树编排能力的构建。决策引擎是风控的大脑,而决策树的编排能力和体验是构建大脑的手段,如何构建高效、丝滑、稳定可靠的决策树编排能力,是对风控决策引擎的一大挑战,本篇文章和大家分享一下过往构建心得。背景任何系统在初期构建肯定不是往“......
  • 【业务安全实战演练】业务流程乱序测试07
    一、流程乱序测试1、测试原理和方法该项测试主要针对业务流程的处理流程是否正常,确保攻击者无法通过技术手段绕过某些重要流程步骤,检验办理业务过程中是否有控制机制来保证其遵循正常流程。例如业务流程分为三步:第一步,注册并发送验证码;第二步,输入验证码;第三步,注册成功。在第三......
  • Java 并发编程在生产应用场景及实战
    背景介绍为什么需要学习Java并发?从提升性能角度来说提升了对CPU的使用效率:目前生产的服务器大多数都是多核,标配的机器都是8C/16G。操作系统会将不同的线程分配给不同的核心处理,理论上,有多少核心就有多少个线程并行执行。如果没有并发编程,CPU的利用率将极大的浪费,假设当......
  • 【中小型企业网络实战案例 一】规划、需求和基本配置
    原创:厦门微思网络案例拓扑图案例需求在中小园区中,S5735通常部署在网络的接入层,S8700通常部署在网络的核心,出口路由器一般选用AR系列路由器。核心交换机配置VRRP保证网络可靠性,配置负载分担有效利用资源。每个部门业务划分到一个VLAN中,部门间的业务在CORE上通过VLANIF三层互通。核心......
  • 构建陪诊预约系统:技术实战指南
    在医疗科技的飞速发展中,陪诊预约系统的应用为患者和陪诊人员提供了更为便捷和贴心的服务。本文将带领您通过技术实现,构建一个简单而实用的陪诊预约系统,以提升医疗服务的效率和用户体验。技术栈选择在开始之前,我们需要选择适用于陪诊预约系统的技术栈:前端:使用React.js构建交互界面......
  • 【Pytorch基础实战】第二节,卷积神经网络
    项目地址https://gitee.com/wxzcch/pytorchbase/tree/master/leason_2源码importtorchfromtorchimportnn,optimfromtorch.autogradimportVariablefromtorch.utils.dataimportDataLoaderfromtorchvisionimportdatasets,transforms#定义一些超参数batch_......
  • Unity 3D定点数物理引擎实战系列1.1BEPUphysicsint 3D定点数物理引擎介绍
    1.1BEPUphysicsint3D定点数物理引擎介绍对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀帧同步的游戏中如果用物理引擎,为了保证不同设备上的结果一致,需要采用定点数来计算迭代游戏过程中的物理运算。也就是我们通常说的定点数物理引擎(确定性物理......