重温设计模式--设计模式七大原则

文章目录

  • 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关系)而不是继承来达到软件复用的目的。
  • 组合是一种强“拥有”关系,体现部分和整体的生命周期是一致的,例如鸟和翅膀,翅膀作为鸟的一部分,当鸟不存在时,翅膀也不存在了。聚合是一种弱“拥有”关系,部分可以独立于整体存在,例如雁群和大雁,大雁可以离开雁群独立生存。
  1. 与继承复用对比

    • 继承复用的缺点
      • 强耦合性:在继承关系中,子类与父类紧密耦合。例如,有一个基类“Vehicle(交通工具)”,它有两个子类“Car(汽车)”和“Motorcycle(摩托车)”。如果在Vehicle类中添加一个新的方法“repair(维修)”,那么Car和Motorcycle类都会继承这个方法。但如果Car类需要对“repair”方法有不同的实现,比如汽车维修可能涉及更多复杂的检查项目,就需要重写这个方法。这可能会导致代码在继承体系中频繁修改,而且一旦父类发生变化,子类可能会受到意外的影响。
      • 缺乏灵活性:继承关系在编译时就已经确定,不能在运行时改变。比如一个基于继承的图形绘制系统,有基类“Shape(形状)”和子类“Circle(圆)”“Rectangle(矩形)”等。如果想要在运行时动态地改变一个形状对象从圆形变成矩形,使用继承就很难实现这种灵活的转换。
    • 组合/聚合复用的优点
      • 松耦合:组合和聚合关系使得各个类之间相对独立。以汽车为例,可以有一个“Engine(引擎)”类和一个“Car”类,它们通过组合关系关联。“Car”类拥有一个“Engine”类的对象作为其成员。如果“Engine”类的内部实现发生变化,比如改进了引擎的燃油喷射系统,只要“Engine”类对外提供的接口不变,“Car”类的代码基本不需要修改。
      • 灵活性高:在运行时可以方便地改变组合或聚合的对象。例如,在一个游戏开发中,角色的武器是通过组合的方式添加到角色身上的。可以在游戏运行过程中,根据游戏情节的发展,为角色更换不同的武器,只需要重新组合武器对象和角色对象即可。
  2. 应用场景示例

    • 游戏开发中的道具系统:假设正在开发一款角色扮演游戏。有一个“Player(玩家)”类,玩家可以拥有不同的“Item(道具)”。“Player”类和“Item”类之间是聚合关系,因为玩家可以捡起或丢弃道具。可以通过在“Player”类中定义一个集合(如列表)来存储玩家拥有的道具。
  3. 遵循原则的好处

    • 提高代码的可维护性:由于类之间的耦合度降低,当对某个类进行修改时,对其他类的影响范围较小。这样在维护代码时,更容易定位和解决问题。
    • 增强代码的可扩展性:方便添加新的功能。例如在上述游戏道具系统中,如果要添加一种新的道具类型,只需要创建新的道具类并实现其功能,然后在玩家类中稍作修改(如果需要),就可以将新道具集成到游戏中,而不会对原有的游戏系统造成大规模的破坏。
    • 提升代码的复用性:可以更好地复用已有的类。比如在不同的游戏场景或者不同的游戏角色中,可以复用“Item”类的各种道具,通过组合或聚合的方式将它们添加到不同的角色或场景中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GiliSoft AI Toolkit v10.1

Gilisoft AI Toolkit是一个综合性的软件包,为企业和个人提供了一个集成人工智能技术到其工作流程中的解决方案。该软件包包括了多种与人工智能相关的工具,如聊天机器人、光学字符识别(OCR)、文本到语音(TTS)和自动语音识别(ASR)软件。它的目的是通过各种…

四种自动化测试模型实例及优缺点详解

一、线性测试 1.概念: 通过录制或编写对应应用程序的操作步骤产生的线性脚本。单纯的来模拟用户完整的操作场景。 (操作,重复操作,数据)都混合在一起。 2.优点: 每个脚本相对独立,且不产生…

git自己模拟多人协作

目录 一、项目克隆 二、多人协作 1.创建林冲仓库 2.协作处理 3.冲突处理 三、分支推送协作 1.创建develop分支 2.发现git push无法把develop推送到远程 ​编辑 3.本地的分支推送到远程分支 四、分支拉取协作 五、远程分支的删除 远程仓库用的gitee 一、项目克隆 …

数据结构---------二叉树前序遍历中序遍历后序遍历

以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例&#xff0c;包括递归和非递归&#xff08;借助栈实现&#xff09;两种方式&#xff1a; 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…

多智能体/多机器人网络中的图论法

一、引言 1、网络科学至今受到广泛关注的原因&#xff1a; &#xff08;1&#xff09;大量的学科&#xff08;尤其生物及材料科学&#xff09;需要对元素间相互作用在多层级系统中所扮演的角色有更深层次的理解&#xff1b; &#xff08;2&#xff09;科技的发展促进了综合网…

电脑ip地址会变化吗?电脑ip地址如何固定

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识符&#xff0c;对于网络通信至关重要。然而&#xff0c;许多用户可能会发现&#xff0c;自己的电脑IP地址并非一成不变&#xff0c;而是会随着时间的推移或网络环境的变化而发生变化。这种变化有时会给用户带来困扰&#…

每天40分玩转Django:Django国际化

Django国际化 一、今日学习内容概述 学习模块重要程度主要内容国际化基础⭐⭐⭐⭐⭐基本概念、配置设置字符串翻译⭐⭐⭐⭐⭐翻译标记、消息文件模板国际化⭐⭐⭐⭐模板标签、过滤器动态内容翻译⭐⭐⭐⭐模型字段、表单翻译 二、国际化基础配置 # settings.py# 启用国际化 …

【人工智能离散数学基础】——深入详解图论:基础图结构及算法,应用于图神经网络等

深入详解图论&#xff1a;基础图结构及算法&#xff0c;应用于图神经网络等 图论&#xff08;Graph Theory&#xff09;是数学中研究图这种离散结构的分支&#xff0c;广泛应用于计算机科学、网络分析、人工智能等领域。随着图神经网络&#xff08;Graph Neural Networks, GNNs…

【docker】docker desktop 在windows上支持 host模式

针对以前的情况&#xff0c;对于 Windows 和 macOS 用户&#xff0c;是不能够使用host模式的。只能在linux上才能够使用 更新日志 docker desktop 在4.34.0版本&#xff0c;开始支持host模式。

【ALGC】探秘 ALGC—— 卓越数据处理能力的科技瑰宝

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 在大数据时代&#xff0c;如何高效地处理和分析海量数据是一个核心挑战。ALGC&#xff08;Advanced Learning and Generalized Comp…

FPGA实现MIPI转FPD-Link车载同轴视频传输方案,基于IMX327+FPD953架构,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博主所有FPGA工程项目-->汇总目录我这里已有的 MIPI 编解码方案 3、本 MIPI CSI-RX IP 介绍4、详细设计方案设计原理框图IMX327 及其配置FPD-Link视频串化-解串方案MIPI CSI RX图像 ISP 处理图像缓存HDMI输出工程源码架构 5、…

STM32 与 AS608 指纹模块的调试与应用

前言 在嵌入式系统中&#xff0c;指纹识别作为一种生物识别技术&#xff0c;广泛应用于门禁系统、考勤机、智能锁等场景。本文将分享如何在 STM32F103C8T6 开发板上使用 AS608 指纹模块&#xff0c;实现指纹的录入和识别功能。 硬件准备 STM32F103C8T6 开发板AS608 指纹模块…

Linux Shell 基础教程⑧

Shell 教程 Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Ke…

网络刷卡器的功能和使用场景

网络刷卡器是一种连接互联网的设备&#xff0c;能够通过网络将读取到的各种卡片信息传输至服务器进行处理。这类刷卡器通常支持多种类型的卡片&#xff0c;如银行卡、身份证、会员卡、公交卡等&#xff0c;并运用现代信息技术确保数据的安全性和高效性&#xff0c;功能十分强大…

Centos7下的根口令重置与GRUB修复

目录 1. 利用GRUB进入单用户模式重置根口令&#xff1b; 步骤较多方法 步骤较少方法&#xff1a;这里主要是把重新以rw方式挂载的步骤换为了在编辑模式直接修改 2. 利用Linux系统安装光盘进入急救模式重置根口令&#xff1b; 3. 如果GRUB损坏&#xff0c;利用Linu…

赋能新一代工业机器人-望获实时linux在工业机器人领域应用案例

在工业4.0蓬勃发展的当下&#xff0c;工业机器人作为制造业转型升级的中流砥柱&#xff0c;正朝着超精密、极速响应的方向全力冲刺。然而&#xff0c;为其适配理想的望获实时Linux系统&#xff0c;却犹如寻找开启宝藏之门的关键钥匙&#xff0c;成为众多企业在智能化进程中的棘…

“无需代码,一句需求,立刻看到你的创意变成网页”==>前端AI工具 “V0”

想象一下&#xff0c;一个能帮你跳过所有烦人的代码编写过程&#xff0c;直接根据你的需求生成页面的 AI&#xff01;没错&#xff0c;这就是 v0&#xff01;你只需要用自然语言描述你想要的界面&#xff0c;v0 就会挥一挥它的“魔法鼠标”&#xff0c;立刻生成漂亮的 UI 代码。…

C语言(一)——初识C语言

目录 简单认识一段代码 数据类型 变量和常量 变量的作用域和变量的生命周期 常量 字符串 转义字符 注释 函数 数组 操作符 关键字 结构体 结构的声明 结构成员的类型 结构体变量的初始化 结构体传参 简单认识一段代码 main()函数是程序的入口&#xff0c;所以…

频繁拿下定点,华玉高性能中间件迈入商业化新阶段

伴随着智能驾驶渗透率的快速增长&#xff0c;中国基础软件市场开始进入黄金窗口期。 近日&#xff0c;华玉通软&#xff08;下称“华玉”&#xff09;正式获得某国内头部轨道交通产业集团的智能化中间件平台定点项目。这将是华玉在基础软件领域深耕和商业化发展过程中的又一重…

怎么学习数据结构与算法?

数据结构与算法 提及数据结构与算法&#xff0c;许多人可能会不自觉地皱起眉头。似乎在不知不觉中&#xff0c;以字节跳动为代表的一批公司&#xff0c;在面试环节开始了一场针对算法的连环盘问。若非事先系统地刷过一系列算法题目&#xff0c;想要轻松通过这一关&#xff0c;…