重温设计模式--设计模式七大原则
文章目录
- 1、开闭原则(Open - Closed Principle,OCP)
- 定义:
- 示例:
- 好处:
- 2、里氏替换原则(Liskov Substitution Principle,LSP)
- 定义:
- 示例:
- 好处:
- 3、依赖倒置原则(Dependency Inversion Principle,DIP)
- 定义:
- 示例:
- 好处:
- 4、单一职责原则(Single Responsibility Principle,SRP)
- 定义:
- 示例:
- 好处:
- 5、接口隔离原则(Interface Segregation Principle,ISP)
- 定义:
- 示例:
- 好处:
- 6、迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle)
- 定义:
- 示例:
- 好处:
- 7、合成聚合复用原则
1、开闭原则(Open - Closed Principle,OCP)
定义:
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需要对软件系统进行功能扩展时,应该通过添加新的代码(类、模块、函数等)来实现,而不是修改已有的代码。
示例:
以一个图形绘制系统为例,假设有一个绘制圆形的类CircleDrawer,如果要添加绘制矩形的功能,不应该直接修改CircleDrawer类。而是创建一个新的RectangleDrawer类来实现绘制矩形的功能。这样,在不修改已有CircleDrawer类的情况下扩展了系统的功能。
好处:
开闭原则可以提高软件系统的可维护性和可扩展性。因为修改已有的代码可能会引入新的错误或者影响到其他部分的功能,而通过添加新的代码来扩展功能可以将新功能的影响范围控制在新添加的部分。
2、里氏替换原则(Liskov Substitution Principle,LSP)
定义:
所有引用基类(父类)的地方必须能透明地使用其子类的对象。也就是说,子类对象应该能够替换父类对象,并且程序的行为和结果不会发生改变。
示例:
假设有一个基类Vehicle,有一个方法calculateSpeed()。有两个子类Car和Bicycle。根据里氏替换原则,在任何使用Vehicle类型对象来调用calculateSpeed()方法的地方,无论是使用Car对象还是Bicycle对象,都应该能够正确地计算出速度,并且不会导致程序出现错误或者不符合预期的行为。
好处:
里氏替换原则有助于保证程序的正确性和稳定性。它强制要求子类在继承父类时,不能改变父类原有的行为语义,从而避免了在多态调用时出现意外的结果。
里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
子类中可以增加自己特有的方法。
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
子类不能覆盖父类的非抽象方法,降低耦合性,提高复用。
3、依赖倒置原则(Dependency Inversion Principle,DIP)
定义:
高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。简单来说,就是要面向接口编程,而不是面向具体的实现编程。
示例:
在一个电商系统中,高层的订单处理模块不应该直接依赖于低层的数据库存储模块。而是应该定义一个抽象的存储接口,订单处理模块依赖这个抽象接口,而数据库存储模块实现这个抽象接口。这样,如果要更换数据库存储方式(如从关系型数据库转换为非关系型数据库),只要新的存储模块实现了相同的抽象接口,就不会影响到订单处理模块。
好处:
依赖倒置原则可以降低模块之间的耦合度,提高系统的灵活性和可维护性。当系统的底层实现发生变化时,只要抽象接口不变,高层模块就不需要修改。
4、单一职责原则(Single Responsibility Principle,SRP)
定义:
一个类应该只有一个引起它变化的原因。也就是说,一个类应该只负责一项职责。
示例:
以一个用户管理系统为例,User类应该只负责与用户信息相关的操作,如获取用户姓名、年龄、修改用户密码等。而不应该同时负责用户登录验证的功能,登录验证应该由另一个专门的LoginValidator类来负责。这样,当用户信息的管理规则发生变化(如添加新的用户属性)时,只需要修改User类;当登录验证的方式发生变化(如添加验证码验证)时,只需要修改LoginValidator类。
好处:
单一职责原则可以使类的职责更加明确,提高类的内聚性,降低类的复杂度。这样在系统发生变化时,更容易定位和修改相关的代码,减少了因为一个类的职责过多而导致的代码修改风险。
5、接口隔离原则(Interface Segregation Principle,ISP)
定义:
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
示例:
假设有一个打印机接口Printer,包含了打印文档、扫描文档、传真文档等多个方法。但对于一个只需要打印功能的客户端(如一个简单的文本编辑器)来说,它不应该依赖包含扫描和传真功能的打印机接口。应该将打印机接口拆分成更小的接口,如Printable接口(只包含打印方法)、Scannable接口(只包含扫描方法)、Faxable接口(只包含传真方法),让客户端只依赖它需要的接口。
好处:
接口隔离原则可以避免客户端依赖不需要的接口,减少了接口的臃肿和客户端的负担。同时也提高了系统的灵活性和可维护性,因为当某个接口的功能发生变化时,只有依赖这个接口的客户端才会受到影响。
6、迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle)
定义:
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
示例:
在一个公司管理系统中,员工类Employee可能会使用部门类Department的一些信息。但是根据迪米特法则,Employee类不应该直接访问Department类的内部成员(如其他员工的信息),而是应该通过Department类提供的有限的接口(如获取部门经理的信息)来获取所需的信息。
好处:
迪米特法则可以降低类之间的耦合度,使系统的结构更加松散,提高系统的可维护性和可扩展性。因为一个类对其他类的了解越少,当其他类发生变化时,对这个类的影响就越小。
7、合成聚合复用原则
- (Composite/Aggregate Reuse Principle,CARP)也叫组合/聚合复用原则。它是面向对象设计原则之一,指的是尽量使用对象组合(has - a关系)或聚合(contains - a关系)而不是继承来达到软件复用的目的。
- 组合是一种强“拥有”关系,体现部分和整体的生命周期是一致的,例如鸟和翅膀,翅膀作为鸟的一部分,当鸟不存在时,翅膀也不存在了。聚合是一种弱“拥有”关系,部分可以独立于整体存在,例如雁群和大雁,大雁可以离开雁群独立生存。
-
与继承复用对比
- 继承复用的缺点
- 强耦合性:在继承关系中,子类与父类紧密耦合。例如,有一个基类“Vehicle(交通工具)”,它有两个子类“Car(汽车)”和“Motorcycle(摩托车)”。如果在Vehicle类中添加一个新的方法“repair(维修)”,那么Car和Motorcycle类都会继承这个方法。但如果Car类需要对“repair”方法有不同的实现,比如汽车维修可能涉及更多复杂的检查项目,就需要重写这个方法。这可能会导致代码在继承体系中频繁修改,而且一旦父类发生变化,子类可能会受到意外的影响。
- 缺乏灵活性:继承关系在编译时就已经确定,不能在运行时改变。比如一个基于继承的图形绘制系统,有基类“Shape(形状)”和子类“Circle(圆)”“Rectangle(矩形)”等。如果想要在运行时动态地改变一个形状对象从圆形变成矩形,使用继承就很难实现这种灵活的转换。
- 组合/聚合复用的优点
- 松耦合:组合和聚合关系使得各个类之间相对独立。以汽车为例,可以有一个“Engine(引擎)”类和一个“Car”类,它们通过组合关系关联。“Car”类拥有一个“Engine”类的对象作为其成员。如果“Engine”类的内部实现发生变化,比如改进了引擎的燃油喷射系统,只要“Engine”类对外提供的接口不变,“Car”类的代码基本不需要修改。
- 灵活性高:在运行时可以方便地改变组合或聚合的对象。例如,在一个游戏开发中,角色的武器是通过组合的方式添加到角色身上的。可以在游戏运行过程中,根据游戏情节的发展,为角色更换不同的武器,只需要重新组合武器对象和角色对象即可。
- 继承复用的缺点
-
应用场景示例
- 游戏开发中的道具系统:假设正在开发一款角色扮演游戏。有一个“Player(玩家)”类,玩家可以拥有不同的“Item(道具)”。“Player”类和“Item”类之间是聚合关系,因为玩家可以捡起或丢弃道具。可以通过在“Player”类中定义一个集合(如列表)来存储玩家拥有的道具。
-
遵循原则的好处
- 提高代码的可维护性:由于类之间的耦合度降低,当对某个类进行修改时,对其他类的影响范围较小。这样在维护代码时,更容易定位和解决问题。
- 增强代码的可扩展性:方便添加新的功能。例如在上述游戏道具系统中,如果要添加一种新的道具类型,只需要创建新的道具类并实现其功能,然后在玩家类中稍作修改(如果需要),就可以将新道具集成到游戏中,而不会对原有的游戏系统造成大规模的破坏。
- 提升代码的复用性:可以更好地复用已有的类。比如在不同的游戏场景或者不同的游戏角色中,可以复用“Item”类的各种道具,通过组合或聚合的方式将它们添加到不同的角色或场景中。
相关文章:

重温设计模式--设计模式七大原则
文章目录 1、开闭原则(Open - Closed Principle,OCP)定义:示例:好处: 2、里氏替换原则(Liskov Substitution Principle,LSP)定义:示例:好处&#…...
LeetCode429周赛T4
最小化二进制字符串中最长相同子字符串的长度 在处理二进制字符串问题时,优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题:给定一个长度为 n 的二进制字符串 s 和一个整数 numOps,通过最多 numOps 次位翻转操作&am…...

详解MySQL在Windows上的安装
目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网,找到DOWNLOADS 然后往下翻,找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载,选择No thanks,just start my download. 然后双击进行…...

【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】
本教程的知识点为:操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 …...

软件测试面试题和简历模板(面试前准备篇)
一、问题预测 1、让简单介绍下自己(这个不用说了每次面试开场) 面试官,你好,我叫xxx,xx年本科毕业,从事软件测试将近3年的时间。在此期间做过一些项目也积累过一些经验,能够独立地完成软件测试…...

Linux 基本使用和程序部署
1. Linux 环境搭建 1.1 环境搭建方式 主要有 4 种: 直接安装在物理机上。但是Linux桌面使用起来非常不友好,所以不建议。[不推荐]。使用虚拟机软件,将Linux搭建在虚拟机上。但是由于当前的虚拟机软件(如VMWare之类的)存在一些bugÿ…...
uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能
前端部分 点击按钮,获取手机号 <button open-type"getPhoneNumber" getphonenumber"bindGetPhoneNumber" hover-class"none"class"btn-purity">一键获取</button> 传入openid和code bindGetPhoneNumber(e) …...
CSS系列(27)- 图形与滤镜详解
前端技术探索系列:CSS 图形与滤镜详解 🎨 致读者:探索CSS的艺术表现力 👋 前端开发者们, 今天我们将深入探讨 CSS 图形和滤镜效果,学习如何创建引人注目的视觉效果。 基础图形 🚀 几何形状…...

Docker 技术系列之安装多版本Mysql5.6和Mysql5.7
image 大家好,后面的就不是关于MAC专有的内容,基本是跟Java环境,基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的,不用担心。 上一篇,我们安装好对应的Docker之后,感受到了它的便利。接…...
理解并使用Linux 内核中的 Tracepoint
理解并使用Linux 内核中的 Tracepoint 1. 引言 1.1 为什么需要 Tracepoint? 在内核调试与性能分析中,传统的 printk 方法虽然简单直接,但存在几个显著的局限性: 日志噪音:printk 会将所有输出无差别地记录到系统日…...

centos7中Gbase8s数据库安装,以及数据导入遇到的一系列问题
centos7中Gbase8s数据库安装,以及遇到的一系列问题 以下是我在centos7上安装gbase8s数据库遇到的一系列问题,包括数据库安装,数据导入,数据连接,不能完全作为标准,只可作为类似问题参考,有问题…...

AW36518芯片手册解读(3)
接前一篇文章:AW36518芯片手册解读(2) 二、详述 3. 功能描述 (1)上电复位 当电源电压VIN降至预定义电压VPOR(典型值为2.0V)以下时,该设备会产生复位信号以执行上电复位操作&#x…...

MySQL的REPEATABLE READ事务隔离级别
本文隔离级别: T1内读T2的update数据 首先开两个事务(左二) 事务1修改成李四,提交 事务2再读还是张三,也就是说,记录的数据从事务开始时一直到结束,读的都是同一个版本,读不到T2未提交的此条记录修改&…...
sqoop的参数有哪些?
Sqoop 是一款用于在 Hadoop 与关系型数据库之间进行数据传输的工具,它有很多参数,可分为通用参数、导入参数和导出参数等,以下是一些常见的参数介绍: 通用参数 --connect 说明:指定要连接的关系型数据库的 JDBC URL。…...

动态规划<四> 回文串问题(含对应LeetcodeOJ题)
目录 引例 其余经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 引例 OJ 传送门Leetcode<647>回文子串 画图分析: 使用动态规划解决 原理:能够将所有子串是否是回文的信息保存在dp表中 在使用暴力方法枚举出所有子串,是…...

跨模态知识迁移:基于预训练语言模型的时序数据建模
在NLP和CV领域,通常通过在统一的预训练模型上进行微调,能够在各自领域的下游任务中实现SOTA(最先进)的结果。然而,在时序预测领域,由于数据量相对较少,难以训练出一个统一的预训练模型来覆盖所有…...

重温设计模式--职责链模式
文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它旨在将请求的发送者和多个接收者解耦,让多个对象都有机会处理请求&a…...

git冲突解决
git冲突解决 最近遇到了一次git冲突的问题 起因是因为最近公司数据推送部分重构,负责重构的同事就改动了我的一小部分推送的代码,然后等我开发完合并到远程master的时候,报了merge冲突。我对于git工具确实不是很熟练,只是学习了…...
Java学习笔记(14)--面向对象编程
面向对象基础 学习资料来自多态 - Java教程 - 廖雪峰的官方网站 目录 面向对象基础 Override 多态 举个例子 覆写Object方法 调用super final 练习 小结 Override 在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写&…...
《Swift 字面量》
《Swift 字面量》 介绍 在 Swift 编程语言中,字面量是一种表示源代码中固定值的表达方式。字面量可以直接表示数字、字符串、布尔值等基本数据类型,为编程提供了简洁和直观的方式。Swift 支持多种类型的字面量,包括整数字面量、浮点数字面量…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...