设计模式之开闭原则:如何优雅地扩展软件系统

在现代软件开发中,设计模式是解决常见问题的最佳实践。其中,开闭原则作为面向对象设计的六大基本原则之一,为软件系统的可维护性和扩展性提供了强大的支持。本文将深入探讨开闭原则的核心理念,以及如何在实际项目中运用这一原则,以便更好地设计软件系统。
一、开闭原则的核心思想
开闭原则,也被称为“对扩展开放,对修改封闭”,意味着软件实体(如类、模块、函数等)应该通过扩展来增加功能,而不是通过修改已有的代码。这意味着在设计软件时,我们应该尽量使代码具有可复用性和可扩展性,以便于在未来添加新功能时不需要修改已有的代码。
二、开闭原则在实践中的应用
假设我们正在设计一个电商系统,其中包含不同类型的商品,有普通商品和折扣商品,每种商品有不同的价格计算方式。
Product接口
一开始我们有一个Product接口
public interface Product {double getPrice();
}
普通商品类
public class NormalProduct implements Product {private double price;public NormalProduct(double price) {this.price = price;}@Overridepublic double getPrice() {return this.price;}
}
随着业务发展,我们需要添加折扣商品,如果直接修改Product类或者NormalProduct类来支持折扣逻辑,就违反了开闭原则。正确的做法是扩展一个新的类。
折扣商品类
public class DiscountedProduct implements Product {private double originalPrice;private double discountRate;public DiscountedProduct(double originalPrice, double discountRate) {this.originalPrice = originalPrice;this.discountRate = discountRate;}@Overridepublic double getPrice() {return this.originalPrice * (1 - discountRate);}
}
这样,在添加新的折扣商品类型时,我们并没有修改原有的Product接口或NormalProduct类,而是增加了新的实现类DiscountedProduct来满足新的需求,这就是开闭原则的体现。
在客户端代码中,可以通过产品接口处理不同类型的商品。
购物车类
public class ShoppingCart {private List<Product> products;public void addProduct(Product product) {products.add(product);}public double getTotalPrice() {return products.stream().mapToDouble(Product::getPrice).sum();}
}
上述代码中的ShoppingCart类不关心具体的产品类型,只要求产品实现Product接口,因此当添加新的产品类型时,购物车的逻辑不需要做任何修改,保持了对修改的封闭性,同时对新的产品类型(扩展)则是开放的。
三、总结
开闭原则是软件设计的核心思想之一,它鼓励我们通过扩展来增加新功能,而不是通过修改已有代码。在实际项目中运用开闭原则,需要我们注重抽象层设计、策略模式和装饰器模式等设计模式的运用。通过遵循开闭原则,我们可以设计出更加灵活、可扩展的软件系统,从而降低维护成本、提高软件质量。
相关文章:
设计模式之开闭原则:如何优雅地扩展软件系统
在现代软件开发中,设计模式是解决常见问题的最佳实践。其中,开闭原则作为面向对象设计的六大基本原则之一,为软件系统的可维护性和扩展性提供了强大的支持。本文将深入探讨开闭原则的核心理念,以及如何在实际项目中运用这一原则&a…...
Python Pandera 用于数据验证和清洗:是一个强大的工具用起来
今天为大家分享一个非常好用的 Python 库 - pandera。 Github地址:https://github.com/unionai-oss/pandera 在数据科学和数据分析中,数据的质量至关重要。不良的数据质量可能导致不准确的分析和决策。为了确保数据的质量,Python Pandera 库…...
英诺赛科推出BMS方案,搭载100V双向导通VGaN
BMS 俗称电池保姆或电池管家,主要是为了智能化管理及维护各个电池单元,防止电池出现过充电和过放电,保障电池安全使用的同时延长使用寿命。 当前市面上出现的电池管理系统大多数采用 Si MOS,由于 Si MOSFET 具有寄生二极管&#x…...
如何用Mac工具制作“苹果高管形象照”
大伙儿最近有没有刷到“苹果高管形象照”风格,详细说来就是: 以苹果官网管理层简介页面中,各位高管形象照为模型,佐以磨皮、美白、高光等修图术,打造的看上去既有事业又有时间有氧的证件照,又称“苹…...
回环检测算法:Stable Trangle Descriptor
回环检测是指检测传感器的两次测量(如图像、激光雷达扫描)是否发生在同一场景,它是对于SLAM问题至关重要。基于激光雷达的回环检测应该满足如下要求: 无论视点如何变化,回环检测方法应该实现旋转和平移不变性…...
MetaGPT入门(二)
接着MetaGPT入门(一),在文件里再添加一个role类 class SimpleCoder(Role):def __init__(self,name:str"Alice",profile:str"SimpleCoder",**kwargs):super().__init__(name,profile,**kwargs)self._init_actions([Write…...
AI嵌入式K210项目(4)-FPIOA
文章目录 前言一、FPIOA是什么?二、FPIOA代码分析总结 前言 磨刀不误砍柴工,在正式开始学习之前,我们先来了解下K210自带的FPIOA,这个概念可能与我们之前学习STM32有很多不同,STM32每个引脚都有特定的功能,…...
FPGA开发设计
一、概述 FPGA是可编程逻辑器件的一种,本质上是一种高密度可编程逻辑器件。 FPGA的灵活性高、开发周期短、并行性高、具备可重构特性,是一种广泛应用的半定制电路。 FPGA的原理 采用基于SRAM工艺的查位表结构(LUT),…...
上海亚商投顾:沪指冲高回落 旅游板块全天强势
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 沪指昨日冲高回落,创业板指跌近1%,北证50指数跌超3%。旅游、零售板块全天强势…...
Linux网络--- SSH服务
一、ssh服务简介 1、什么是ssh SSH(Secure Shell)是一种安全通道协议,主要用来实现字符界面的远程登录、远程复制等功能。SSH 协议对通信双方的数据传输进行了加密处理,其中包括用户登录时输入的用户口令,SSH 为建立在…...
2.1 数组
2.1 数组 (1) 概述 定义 在计算机科学中,数组是由一组元素(值或变量)组成的数据结构,每个元素有至少一个索引或键来标识 因为数组内的元素是连续存储的,所以数组中元素的地址,可以通过其索引…...
超维空间M1无人机使用说明书——53、ROS无人机二维码识别与降落——V2升级版本
引言:使用二维码引导无人机实现精准降落,首先需要实现对二维码的识别和定位,可以参考博客的二维码识别和定位内容。本小节主要是通过获取拿到的二维码位置,控制无人机全向的移动和降落,本小节再V1版本的基础上增加了动…...
瑞萨IDE:CS+ for CC进行BootLoader升级时开发环境配置
瑞萨IDE:CS+ for CC进行BootLoader升级时开发环境配置 2023-06-17 726 发布于河北 版权 简介: BootLoader程序设计是常用的嵌入式升级方案之一,通过使用UART、SPI、IIC等接口实现对嵌入式节点的远程升级。本片博文并不是讲解如何实现BootLoader升级程序,而是讲解使用CS+…...
翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二
Streamlit从入门到精通 系列: 翻译: Streamlit从入门到精通 基础控件 一 1. 使用Streamlit显示图表Graphs 1.1 为什么我们需要可视化? 数据可视化通过将数据整理成更容易理解的格式来讲述故事,凸显趋势和异常点。好的可视化能够讲述一个故…...
Java 开源扫雷游戏 JMine 发布新版 3.0 及介绍视频
Java 开源扫雷游戏 JMine 发布新版 3.0 及介绍视频 Java 开源扫雷游戏 JMine 是笔者开发的基于 Swing 的 Java 扫雷游戏,现已发布新版 3.0 及其介绍视频。视频请见: https://www.bilibili.com/video/BV1RK4y1z7Qz/ 老版本 JMine 1.2.5 的介绍视频请见…...
Vue v-model 详解
✨ 专栏介绍 在当今Web开发领域中,构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架,正是为了满足这些需求而诞生。它采用了MVVM架构模式,并通过数据驱动和组件化的方式,使…...
一个超级牛逼的消息推送系统Gotify 使用Gotify来搭建你的消息推送系统
目录 先看效果 简介 1.1创建目录 3.访问服务端 3.1示例 3.2创建应用 4.安装apk 4.1下载apk 4.2安装 4.3配置服务器地址 5.推送消息测试 5.1服务器执行 5.2手机端查看 支持删除 6.源码地址 先看效果 打开应用 简介 gotify 支持的功能如下 可以通过 restapi 发送消…...
【架构设计】单体软件向微服务化演变
单体软件 假设单体软件的各模块如下,其中服务包含许多功能模块,如用户管理模块、商品模块、订单模块、仓库模块; #mermaid-svg-MzWKwMCwfo3PWMGH {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-…...
部署ATS(Apache Traffic Server)和Nginx正向代理服务性能对比
部署ATS(Apache Traffic Server)和Nginx正向代理服务&性能对比 1. 正向代理的用途2. ATS(Apache Traffic Server)正向代理服务器部署3. Nginx正向代理服务器部署4. 性能对比 1. 正向代理的用途 正向代理一般是用于内部网络出去,反向代理一…...
kafka入门(六):日志分段(LogSegment)
日志分段(LogSegment) Kafka的一个 主题可以分为多个分区。 一个分区可以有一至多个副本,每个副本对应一个日志文件。 每个日志文件对应一个至多个日志分段(LogSegment)。 每个日志分段还可以细分为索引文件、日志存储…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
