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

news2024/9/25 13:17:28

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

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

定义

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1324187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图片编辑文字用什么软件?带你了解这5个

图片编辑文字用什么软件&#xff1f;在当今数字化的时代&#xff0c;图片编辑已经成为我们日常生活中不可或缺的一部分。有时候&#xff0c;我们需要在图片上添加文字&#xff0c;以增强图片的视觉效果或传达特定的信息。那么&#xff0c;有哪些可以在图片上编辑文字的软件呢&a…

使用postman时,报错SSL Error: Unable to verify the first certificate

开发中使用postman调用接口&#xff0c;出现以下问题&#xff0c;在确认路径、参数、请求方式均为正确的情况下 解决方法 File - Settings -> SSL certification verification 关闭 找到图中配置&#xff0c;这里默认是打开状态&#xff0c;把它关闭即可&#xff1a;ON …

mysql:查询服务器当前打开的连接数量

使用命令show global status like Threads_connected;可以查询mysql服务器当前打开的连接数量。 例如&#xff0c;查询如下&#xff1a; 启动应用&#xff0c;连接数据库&#xff0c;占用了1个连接&#xff0c;再查询如下&#xff1a; 由输出可以看出&#xff0c;打开的连接…

02 ModBus TCP

目录 一、ModBus TCP 一帧数据格式 二、0x01 读线圈状态 三、0x03读保持寄存器 四、0x05写单个线圈 五、0x06 写单个寄存器 六、0x0f写多个线圈 七、0x10&#xff1a;写多个保持寄存器 八、通信过程 九、不同modbus通信模式的应用场景 一、ModBus TCP 一帧数据格式 其…

JNI逆向

IDA&#xff1a;JNI类型转换 1.IDA高版本&#xff08;IDA 高版本内置了定义的JNI结构体; 如果没有的话&#xff0c;在Views->Open subviews -> Type Libraries 中添加Android ARM的lib即可&#xff09; 解决方法: 只需要对JNIEnv 指针&#xff08;JNIEnv * &#xff09…

jQuery实现轮播图代码

简述 一个简单的jQuery轮播图代码,首先,定义了一个slideshow-container的div容器,其中包含了所有轮播图幻灯片。每个幻灯片都包含一个mySlides的类名,并且使用CSS将其隐藏。然后,使用JavaScript代码来控制幻灯片的显示和隐藏。在showSlides()函数中,遍历所有幻灯片并将它…

DDD领域驱动设计(二)

软件系统复杂性的应对 解决复杂和大规模软件的武器可以粗略的归位三种:抽象 分治和知识 抽象: 使用抽象能够精简问题空间&#xff0c;而且问题越小越容易理解。比如你去一个地方 一开始的时候并不需要确定用什么方式到达。分治: 类似算法里面的dp用的就是分治的想法。分割后的…

构建陪诊预约系统:技术实战指南

在医疗科技的飞速发展中&#xff0c;陪诊预约系统的应用为患者和陪诊人员提供了更为便捷和贴心的服务。本文将带领您通过技术实现&#xff0c;构建一个简单而实用的陪诊预约系统&#xff0c;以提升医疗服务的效率和用户体验。 技术栈选择 在开始之前&#xff0c;我们需要选择…

Halcon求三点中心,三角形重心、三角形外接圆外心和内切圆内心

本文涉及几何问题&#xff0c;求角平分线&#xff0c;垂直平分线以及中线&#xff0c;不止可以应用于点和三角形&#xff0c;其他需求可选择性提取。 求角平分线&#xff1a;http://t.csdnimg.cn/QYZOK 求垂直平分线&#xff1a;http://t.csdnimg.cn/A4wWD 三角形的重心&…

JDK bug:ciObjectFactory::create_new_metadata:原因完全解析

文章目录 1、问题2.详细日志2.关键日志3.结论4.JDK&#xff1a;bug最终bug链接&#xff1a; 京东遇到过类似bug各位大佬如果有更详细的解答可以留言。 1、问题 服务不通&#xff0c;接口404&#xff0c;查看日志有一下截图&#xff0c;还有一个更详细的日志 2.详细日志 # #…

如何在公网环境下使用Potplayer访问本地群晖webdav中的影视资源

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是&#xff1a;1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透&#xff0c;映射至公网4 使用固定地址在potplayer访问webdav ​ 国内流媒体平台的内…

青少年CTF-qsnctf-Web-Queen

题目环境&#xff1a; 题目难度&#xff1a;★★ 题目描述&#xff1a;Q的系统会不会有漏洞&#xff1f; 看到了登录窗口&#xff0c;使用burp suite工具进行抓包 burp suite抓包 admin 1 Repeater重放Send放包 Your IP is not the administrator’s IP address! 您的IP不是管理…

张驰咨询:程序员如何利用六西格玛培训优化代码质量和工作效率?

在当今这个以数据驱动决策和追求极致效率为标杆的商业世界中&#xff0c;“六西格玛”(Six Sigma)不再仅是精益管理的术语&#xff0c;它已经成为提升个人和组织竞争力的重要法宝。让我们一起揭开六西格玛在职场培训中的神秘面纱&#xff0c;探索如何用它来精进自己的工作和生活…

位操作符详解(C语言)

前言 C语言中的位操作符是用来对数据的二进制表示进行位级操作的运算符。这些操作符包括位与&#xff08;&&#xff09;、位或&#xff08;|&#xff09;、位异或&#xff08;^&#xff09;、位取反&#xff08;~&#xff09;&#xff0c;这些位操作符可以用来进行各种位级…

御云出海记 | 引领泰国数字化基础设施,共推AI应用未来

12月18日&#xff0c;2023华为云泰国AI峰会如期举行。此次峰会是华为云与泰国数字经济与社会部&#xff08;MDES&#xff09;共同举办&#xff0c;汇聚了政府代表、行业专家、本地客户、合作伙伴及中国企业&#xff0c;共同探讨泰国的AI发展和数字化转型。 万博智云有幸作为华…

通用的java中部分方式实现List<自定义对象>转为List<Map>

自定义类 /*** date 2023/12/19 11:20*/ public class Person {private String name;private String sex;public Person() {}public Person(String name, String sex) {this.name name;this.sex sex;}public String getName() {return name;}public String getSex() {return…

100GPTS计划-AI写作VersatileWriter

地址 https://chat.openai.com/g/g-zHErU9z9m-versatile-writer https://poe.com/VersatileWriterGPT 测试 翻译:要求将给定的英语语句翻译成中文。 总结:给出一段文本,要求进行概括和总结。 问答:根据给定段落,提出相关问题并给出答案。 推理:给出前提,进行多步推理并得…

CloudPulse:一款针对AWS云环境的SSL证书搜索与分析引擎

关于CloudPulse CloudPulse是一款针对AWS云环境的SSL证书搜索与分析引擎&#xff0c;广大研究人员可以使用该工具简化并增强针对SSL证书数据的检索和分析过程。 在网络侦查阶段&#xff0c;我们往往需要收集与目标相关的信息&#xff0c;并为目标创建一个专用文档&#xff0c…

部分常用算法笔记

一、简单易考 1、冒泡排序 https://www.nowcoder.com/practice/2baf799ea0594abd974d37139de27896 for i:0;i<length;i { for j:0;j<length-i-1;j { if array[j] > array[j1] { array[j1],array[j] array[j],array[j1] } } } 2、求数组最大最小值。 1&#xff09;O(…

Android studio中导入opencv库

具体opencv库的导入流程参考链接&#xff1a;Android Studio开发之路 &#xff08;五&#xff09;导入OpenCV以及报错解决 一、出现的错误&#xff1a;NullPointerException: Cannot invoke “java.io.File.toPath()” because “this.mySdkLocation” is null 解决办法&#…