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

文章目录

  • 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”类的各种道具,通过组合或聚合的方式将它们添加到不同的角色或场景中。

更简单总结

1、单一职责原则
定义:就一个类而言,应该只有一个引起该类变化的原因。
一个类只有一个职责,如果职责过多,代码就会臃肿,可读性更差,也更难以维护,主要体现面向对象的高内聚低耦合。

2、开闭原则(Open Close Principle)
定义:软件实体(类、模块、函数)应该可以扩展,但是不可修改。

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码。

3、依赖倒转原则(Dependence Inversion Principle)
定义:高层模块不应该依赖于低层模块,两者都应该依赖于抽象;
抽象不应该依赖于细节,细节应该依赖于抽象;
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、里氏代换原则(Liskov Substitution Principle)
定义:子类型必须能替换掉它们的父类型。
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范,这个原则在工厂模式体现的比较明显。

5、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

6、迪米特法则,又称最少知道原则(Demeter Principle)
定义:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
简单来说就是一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立,还是体现了面向对象的高内聚低耦合。

7、合成复用原则(Composite Reuse Principle)
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承

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

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

相关文章

第十五章 C++ 数组

C 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声…

企业数字化转型加速,现代 IT 如何用 Datadog 全面提升可观测性?

作为 Gartner 可观测平台魔力象限的领导者,Datadog 凭借全面的功能、直观的用户界面和强大的产品路线图赢得了全球企业的信任。 企业 IT 架构正变得日益复杂,从本地服务器到云端部署,从单体应用向微服务,还有容器、 Kubernetes 等…

渗透Vulnhub-DC-9靶机

本篇文章旨在为网络安全渗透测试行业靶机教学。通过阅读本文,读者将能够对渗透Vulnhub系列DC-6靶机有定的了解 一、信息收集阶段 DC-9靶场信息: DC-9靶场介绍: https://www.vulnhub.com/entry/dc-9,412/ DC-9靶场下载: https://download.vu…

[WASAPI]从Qt MultipleMedia来看WASAPI

[WASAPI] 从Qt MultipleMedia 来看WASAPI 最近在学习有关Windows上的音频驱动相关的知识,在正式开始说WASAPI之前,我想先说一说Qt的Multiple Media,为什么呢?因为Qt的MultipleMedia实际上是WASAPI的一层封装,它在是线…

Linux下编译安装Kokkos

本文记录在Linux下编译安装Kokkos的流程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1oneAPI2024.2.1 一、安装依赖 二、编译安装 参考文献 Mills R T. PETSc/TAO Developments for Early Exascale Systems[J]. 2024.Josef R. A Stud…

HTMLCSS:惊!3D 折叠按钮

这段代码创建了一个具有 3D 效果和动画的按钮,按钮上有 SVG 图标和文本。按钮在鼠标悬停时会显示一个漂浮点动画,图标会消失并显示一个线条动画。这种效果适用于吸引用户注意并提供视觉反馈。按钮的折叠效果和背景渐变增加了页面的美观性。 演示效果 HT…

容器技术所涉及Linux内核关键技术

容器技术所涉及Linux内核关键技术 一、容器技术前世今生 1.1 1979年 — chroot 容器技术的概念可以追溯到1979年的UNIX chroot。它是一套“UNIX操作系统”系统,旨在将其root目录及其它子目录变更至文件系统内的新位置,且只接受特定进程的访问。这项功…

Git远程仓库的多人协作

目录 一.项目克隆 二.多人协作 1.创建林冲仓库 2.协作处理 3.处理冲突 三.分支推送协作 四.分支拉取协作 五.远程分支的删除 一.项目克隆 我们可以把远程项目克隆到本地形成一个本地的仓库 git clone https://github.com/txjava-teach/txjava-code.git //链接你自己的远…

Docker 部署 plumelog 最新版本 实现日志采集

1.配置plumelog.yml version: 3 services:plumelog:#此镜像是基于plumelog-3.5.3版本image: registry.cn-hangzhou.aliyuncs.com/k8s-xiyan/plumelog:3.5.3container_name: plumelogports:- "8891:8891"environment:plumelog.model: redisplumelog.queue.redis.redi…

Spring常见面试题总结

关于详细介绍,可以看我写的 ( Spring知识点) 这篇文章。 Spring 基础 什么是 Spring 框架? Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说 Spring 框架指的都是 Spring Framework&#xff0c…

Mac系统下 IDEA配置Maven本地仓库

1.为什么需要配置本地仓库? 在软件开发过程中,使用Maven工具进行依赖管理是常见的做法。Maven通过集中管理各种依赖库,能够帮助开发者在项目中轻松地引入所需的第三方库,并确保项目能够顺利构建和部署。然而,在使用Mav…

RGCL:A Review-aware Graph Contrastive Learning Framework for Recommendation

A Review-aware Graph Contrastive Learning Framework for Recommendation 解决的问题 基于评论的推荐可以自然地形成为具有来自相应用户项目评论的边特征的用户项目二分图。那么就可以利用评论感知图中独特的自监督信号来指导推荐的两个组件:用户-项目嵌入学习,用户-项目…

5、mysql的读写分离

主从复制 主从复制的含义 主从复制:在一个mysql的集群当中,至少3台,即主1台,从2台。 当有数据写入时,主负责写入本库,然后把数据同步到从服务器。 一定是在主服务器写入数据,从服务器的写入…

重生之我在异世界学编程之C语言:深入预处理篇(上)

大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 本文目录 引言正文一、预处理的作用与流程&#xf…

信创源代码加密的答案:信创沙箱

在信息化与工业化融合创新(信创)的背景下,企业面临着前所未有的数据安全挑战。SDC沙盒技术以其独特的隔离和保护机制,为信创环境提供了强有力的支持。以下是SDC沙盒在信创支持方面的优势,这些优势体现了其在保护企业数…

计算机网络B重修班-期末复习

[TOC] (计算机网络B重修班-期末复习) 一、单选 (20题,1分/题,共20分) 二、判断 (10题,1分/题,共10分) 三、填空 (10题,1分/题,共10…

结合实例从HCI层分析经典蓝牙连接和配对过程

我们知道,经典蓝牙BREDR的link key协商是在LMP层做的,那么蓝牙Host在鉴权的过程中,会跟BT SOC有哪些交互: 首次配对 在HCI Inuqiry找到想要配对的设备后,Host会调用HCI Create Connection命令去连接对方设备&#xf…

StartAI图生图局部重绘,让画面细节焕发新生!!

在设计的世界里,每一个细节都承载着我们的创意与心血。然而,有时我们总会遇到一些不尽如人意的画面细节,它们如同瑕疵般破坏了整体的和谐与美感。今天,我要向大家推荐一款强大的工具——StartAI的局部重绘功能,它正是我…

VMware vCenter保姆级安装部署(VMware VCenter Nanny Level Installation and Deployment)

VMware vCenter保姆级安装部署教程 VMware vCenter‌是由VMware开发的一款虚拟化管理平台,主要用于管理和监控虚拟化环境中的虚拟机、主机和存储资源。它提供了一个集中控制的平台,简化了虚拟化基础设施的管理工作,提高了资源利用率和灵活性…

蓝牙协议——音量控制

手机设置绝对音量 使用Ellisys查看如下: 使用Wireshark查看如下: 音量的量程是128,0x44的十进制是68,53%或54%音量的计算如下: 68 / 128 53.125%耳机设置绝对音量