开闭原则 (Open/Closed Principle, OCP)

开闭原则 (Open/Closed Principle, OCP)

开闭原则(Open/Closed Principle, OCP)是面向对象设计的五大原则之一。它的基本思想是:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。即在不修改现有代码的基础上,通过扩展(如新增类或方法)来实现新的功能,从而增强系统的灵活性和可维护性。

1. 原则解释

开闭原则要求我们在设计系统时,使其能够轻松地扩展功能,而不需要修改现有的代码。遵循这一原则有以下好处:

  • 增强系统的稳定性:通过避免对现有代码的修改,可以减少引入新错误的风险。
  • 提高系统的灵活性:可以方便地添加新功能,而不影响已有功能。
  • 促进代码的复用:通过扩展已有代码,可以避免重复开发相同功能。

2. 实现开闭原则的方式

为了实现开闭原则,常用的设计技术有以下几种:

  • 抽象类和接口:通过定义抽象类和接口来约定行为,然后通过继承和实现这些抽象类和接口来扩展功能。
  • 策略模式:将算法的实现分离到不同的类中,通过组合方式来实现不同的行为。
  • 装饰器模式:通过对对象进行包装,动态地添加新的行为或功能。

3. 违反开闭原则的例子

假设我们有一个简单的图形绘制程序,可以绘制不同类型的图形(如圆形和矩形)。最初的设计可能如下:

public class GraphicEditor {public void drawShape(Shape shape) {if (shape instanceof Circle) {drawCircle((Circle) shape);} else if (shape instanceof Rectangle) {drawRectangle((Rectangle) shape);}}private void drawCircle(Circle circle) {// 绘制圆形的代码}private void drawRectangle(Rectangle rectangle) {// 绘制矩形的代码}
}public class Shape {// 图形的通用属性和方法
}public class Circle extends Shape {// 圆形的特有属性和方法
}public class Rectangle extends Shape {// 矩形的特有属性和方法
}

在这个设计中,每当我们需要添加新的图形类型(如三角形),就需要修改 GraphicEditor 类,添加新的 if 条件。这违反了开闭原则,因为我们需要修改已有的代码来实现新功能。

4. 遵循开闭原则的改进

为了遵循开闭原则,我们可以通过引入抽象类和接口来改进设计,使其对扩展开放,对修改关闭。

// 图形接口
public interface Shape {void draw();
}// 圆形类
public class Circle implements Shape {@Overridepublic void draw() {// 绘制圆形的代码}
}// 矩形类
public class Rectangle implements Shape {@Overridepublic void draw() {// 绘制矩形的代码}
}// 图形编辑器类
public class GraphicEditor {public void drawShape(Shape shape) {shape.draw();}
}

在这个改进后的设计中,我们通过 Shape 接口定义了图形的绘制行为,每种具体的图形类(如 CircleRectangle)实现了 Shape 接口的 draw 方法。GraphicEditor 类通过调用 Shape 接口的 draw 方法来绘制图形。这样,当我们需要添加新的图形类型时,只需创建一个新的类实现 Shape 接口,而不需要修改 GraphicEditor 类的代码。

5. 使用例子

让我们来看一个具体的使用例子,展示如何遵循开闭原则来进行扩展。

public class Main {public static void main(String[] args) {Shape circle = new Circle();Shape rectangle = new Rectangle();GraphicEditor editor = new GraphicEditor();editor.drawShape(circle);editor.drawShape(rectangle);}
}

在这个例子中,我们创建了一个圆形对象和一个矩形对象,并通过 GraphicEditor 类来绘制它们。当我们需要添加新的图形

类型(例如三角形)时,只需创建一个新的类实现 Shape 接口,而不需要修改现有的代码:

// 三角形类
public class Triangle implements Shape {@Overridepublic void draw() {// 绘制三角形的代码}
}// 使用新的三角形类
public class Main {public static void main(String[] args) {Shape circle = new Circle();Shape rectangle = new Rectangle();Shape triangle = new Triangle();GraphicEditor editor = new GraphicEditor();editor.drawShape(circle);editor.drawShape(rectangle);editor.drawShape(triangle);}
}

通过这种方式,我们可以在不修改 GraphicEditor 类的情况下,轻松地扩展新的图形类型,真正实现了对扩展开放,对修改关闭的设计原则。

6. 总结

开闭原则是面向对象设计中的基本原则之一,通过确保软件实体对扩展开放,对修改关闭,可以提高系统的稳定性、灵活性和可维护性。在实际开发中,遵循开闭原则有助于我们设计出高质量的代码,使系统更加健壮和易于扩展。

希望这个博客对你有所帮助。如果你有任何问题或需要进一步的例子,请随时告诉我!

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

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

相关文章

uniapp实现水印相机

uniapp实现水印相机-livePusher 水印相机 背景 前两天拿到了一个需求,要求在内部的oaApp中增加一个卫生检查模块,这个模块中的核心诉求就是要求拍照的照片添加水印。对于这个需求,我首先想到的是直接去插件市场,下一个水印相机…

多头注意力机制详解:多维度的深度学习利器

引言 多头注意力机制是对基础注意力机制的一种扩展,通过引入多个注意力头,每个头独立计算注意力,然后将结果拼接在一起进行线性变换。本文将详细介绍多头注意力机制的原理、应用以及具体实现。 原理 多头注意力机制的核心思想是通过多个注…

springAMQP自定义fanout交换机进行消息的广播

rabbitmq一共有三种交换机: fanout--广播direct--定向topic--话题 rabbitmq-web端 首先我们需要建立一个名叫cybg.fanout交换机与两个自定义的队列用于测试广播效果 我这里就起名字叫做fanout_queue1&fanout_queue2 项目中: 首先对我们的Liste…

当代政治制度(练习题)

当代政治制度(练习题) *** Rz整理 仅供参考 *** 目前地方人大设立的专门委员会不包括(B.法律审查委员会F.外交事务专门委员会 )答案不确定 等待指点 A.法制委员会 B.法律审查委员会 C.财政经济委员会 D.社会建设委员会 E.农业与…

Go语言基础数据类型、变量及自增语法

本文内容为Go语言的基础数据类型、变量定义和赋值及自增语法介绍。 目录 基础数据类型 变量 先定义后赋值 定义时直接赋值 自动推导定义赋值 平行赋值 自增语法 总结 基础数据类型 int,int8 intl6, int32, int64 uint8... uint64 float32,float64 true/false 变量 …

unity 环形循环切换UI

环形ui管理器 using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using System.Collections; using Unity.VisualScripting;public class LevelSelector : MonoBehaviour {public GameObject levelButtonPrefab; // 关卡按钮的…

Elasticsearch:介绍 retrievers - 搜索一切事物

作者:来自 Elastic Jeff Vestal, Jack Conradson 在 8.14 中,Elastic 在 Elasticsearch 中引入了一项名为 “retrievers - 检索器” 的新搜索功能。继续阅读以了解它们的简单性和效率,以及它们如何增强你的搜索操作。 检索器是 Elasticsearc…

Linux:解决vim打开文件默认为replace模式

现象 Ubuntu打开 vim 默认为 replace 模式 原因 终端的编码设置与目标机器的编码设置不同。 解决方案 修改 vim 配置文件( /etc/vim/vimrc或者~/.vimrc),添加: set termencodingutf-8 set fileformatsunix set encodingprcP.S. vimrc 中注释使用英…

知识图谱与LLMs:实时图分析(通过其关系的上下文理解数据点)

大型语言模型 (LLM) 极大地改变了普通人获取数据的方式。不到一年前,访问公司数据需要具备技术技能,包括熟练掌握各种仪表板工具,甚至深入研究数据库查询语言的复杂性。然而,随着 ChatGPT 等 LLM 的兴起,随着所谓的检索…

Ubuntu系统安装mysql之后进行远程连接

1.首先要配置数据库允许进行远程连接 1.1 打开MySQL配置文件 /etc/mysql/mysql.conf.d/mysqld.cnf sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf1.2 修改 bind-address 行 #按i进入插入模式 bind-address 0.0.0.0 #按 Esc 键退出插入模式。 #输入:wq 然后按 Enter 保存并退…

React学习笔记02-----

一、React简介 想实现页面的局部刷新,而不是整个网页的刷新。AJAXDOM可以实现局部刷新 1.特点 (1)虚拟DOM 开发者通过React来操作原生DOM,从而构建页面。 React通过虚拟DOM来实现,可以解决DOM的兼容性问题&#x…

Window10下安装WSL-Ubuntu20.04

1.开启并更新WSL 1.1开启WSL 首先先来看一下电脑是否能够开启WSL:待补充... 然后再来看一下如何开启WSL:win->设置->应用->应用和功能->程序和功能,如下所示: 最后选择启用或关闭Windows功能,开启两个选项:1.Hyper-V…

工具推荐|语音轻松记笔记,AI帮你识别和润色

# 你日常有没有遇到这样的场景? 偶尔有一些奇思妙想想要记录下来,但没有一个轻量的工具,往往会想着想着就把这个想法抛之脑后。特别是搞短视频的,你也许希望把当时的想法录下来,稍微剪辑下就能出一条不错的口播视频。…

springboot的JWT令牌

生成JWT令牌 依赖 <!--jwt令牌--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>javax.xml.bind<…

【LeetCode】最小栈

目录 一、题目二、解法完整代码 一、题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。 void push(int val) 将元素val推入堆栈。 void pop() 删除堆栈顶部的元…

ACE之ACE_Handle_Set

简介 ACE_Handle_Set是对select io复用中fd_set的封装 结构 #mermaid-svg-dwnlrGqy52ds6ctC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-dwnlrGqy52ds6ctC .error-icon{fill:#552222;}#mermaid-svg-dwnlrGqy52…

微信小程序开发基础知识6----使用npm包

一、小程序对npm的支持与限制 目前&#xff0c;小程序中已经支持使用 npm 安装第三方包&#xff0c;从而来提高小程序的开发效率。但是&#xff0c;在小程序中使用npm 包有如下3个限制: ① 不支持依赖于 Node.js 内置库的包 ② 不支持依赖于浏览器内置对象的包 ③ 不支持依赖于…

Java算法-力扣leetcode-209. 长度最小的子数组

209. 长度最小的子数组 给定一个含有 n ****个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 ****target ****的长度最小的 **** 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度 。 如果不存在符合条件的子数组&#xff0c;…

pico+unity预设配置

picosdk中有很多预设的配置、使用预设配置的方法有 1、创建 XR Origin、展开 XR Origin > Camera Offset&#xff0c;选中 LeftHand Controller。点击 XR Controller (Action-Based) 面板右上角的 预设 按钮 2、打开Assets\Samples\XR Interaction Toolkit\2.5.2\Starter A…

Linux--YUM仓库部署及NFS共享存储

目录 一、YUM仓库服务 1.1 YUM介绍 1.2 yum 常用的命令 1.3 YUM 源的提供方式 1.3.1 配置本地 yum 源仓库 1.3.2 配置 ftp 源 1.3.3 配置http服务源 二、NFS 共享存储 2.1 NFS基本概述 2.2 为什么使用 NFS 共享存储 2.3 NFS 应用场景 2.4 NFS 实现原理 2.5 NFS文件…