面向对象七大设计原则

news2024/11/26 22:20:01

更多Java知识学习


文章目录

  • 前言
  • 一、单一职责原则
    • 定义:
    • 优点:
    • 怎么应用?
  • 二、开闭原则
    • 定义
    • 优点
    • 怎么应用?
  • 三、依赖倒置原则
    • 定义
    • 优点
    • 怎么应用?
  • 四、接口隔离原则
    • 定义
    • 优点
    • 怎么应用?
  • 五、里氏替换原则
    • 定义
    • 继承的优缺点
    • 什么时候使用继承合适呢?
  • 六、迪米特原则
    • 定义
    • 分析
    • 怎么应用?
  • 七、合成/聚合复用原则
    • 定义
    • 前提
    • 怎么应用?
  • 总结
    • 面向对象设计的基本原则
    • 设计原则之间的关系


前言

提示:这里可以添加本文要记录的大概内容:

面向对象学习中的这几大原则不可不知道,只有掌握了这些原则,我们才能更好的理解设计模式。


提示:以下是本篇文章正文内容,下面案例可供参考

一、单一职责原则

定义:

一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。

也就是说一个类只做一件事或者说只有一个原因可能会引起这个类的变化
在这里插入图片描述

优点:

如果没有满足单一原则,一个类会做好多事,这样这个类就会有很多原因会引起他的变化,而且这个类会很难再次被复用;
如果满足了单一原则,一个类只做一件事,相对来讲比较灵活,复用率也比较高

怎么应用?

我们来看一下这个案例
某软件公司开发人员针对CRM(客户关系管理系统)中的客户信息图形统计模块提出了下面的初始设计方案结构图。
在这里插入图片描述
仔细分析一下,在这里面有这样一个类,这个类做了哪些事情呢
在这里插入图片描述
很显然,他现在已经违背了单一职责的原则
因为承担了过多的职责,这样的设计难以实现代码的重用,会拥有多个引起他变化的原因

所以接下来我们用单一职责原则对他来进行重构:
上面我们分析出他有三个职责,那就由三个类分别来实现这三个职责
用单一职责原则对他进行重构设计:
我们设计三个类,每一个类都有自己的工作
在这里插入图片描述

二、开闭原则

定义

一个软件实体(模块,类,函数,等等)应当对扩展开放,对修改关闭。

当我们修改一个软件的需求的时候,可以通过新增代码,也就是扩展的方式来修改,而不能够通过修改代码的方式来修改

优点

因为避免了修改代码的内容,也就避免了因为修改代码而引入新错误的可能

怎么应用?

我们还是用刚刚这个客户关系管理系统
这是我们刚刚重构后的样子
假设现在要对这个客户关系管理系统中的数据库访问功能升级,到Hibernate框架来实现。
我们应该怎样去满足用户的需求
在这里插入图片描述
如果是现在上图这种设计去满足客户需求,我们不得不修改代码的内部,但这样就违背了开闭原则

那么怎么样去修改它呢?我们可以将数据访问这里设置一个接口,到底是什么形式的访问,我们可以用具体的类来实现这个接口

那我们客户使用哪种具体的数据访问,我们可以通过配置文件来实现?
首先可以先扩展一个具体的数据访问方式的类,然后我们去修改这个配置就可以了

所以接下来我们用开闭原则对他来进行重构:
在这里插入图片描述
重构设计后,再扩展数据库访问方式时,不需修改原实体。
也就是说我们可以通过扩展的方式来满足需求的变更,而不去修改代码的内部
这样就满足了开闭原则:对于扩展是开放的;对于修改是封闭的。

三、依赖倒置原则

定义

抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
在这里插入图片描述

优点

如果没有使用依赖倒置原则,当需求发生变更的时候,我们不得不去修改程序代码内部,违背了开闭原则,这样系统灵活性就比较差
如果使用了依赖倒置原则,也就是说我们针对接口编程了,如果用户的需求发生变更,我们添加一个具体实现的类就可以了,也就是说通过扩展的方式实现了用户需求的变更,那么系统的灵活性就比较好
在这里插入图片描述

怎么应用?

某软件公司开发人员在开发CRM(客户关系管理系统)时,经常要将存储在TXT或Excel文件中的客户信息转存到数据库中。
针对这一功能有一这原始设计:
每次需要根据数据来源,更换数据转换类
在这里插入图片描述
如果要是我们对数据转换方式进行了更新,或者添加了新的转换方式,那是不是要修改代码内部?
所以上图的原始设计违反了开闭原则(每当需求发生变更都要去修改代码),更换数据转换类时,需要修改CustomerDAO;
引入新的数据转换类时,仍需要修改CustomerDAO

所以我们用依赖倒置原则对他进行重构:
依赖倒置原则就是要针对接口编程而不是针对实现编程
现在的原始设计中就针对了TXT类型和Excel类型这两个具体的实现类来编程,所以我们就要提取出来一个接口,做到针对接口编程
我们针对具体的转换类提取出来一个抽象的接口,然后这些具体的转换类型实现这个接口,如果需要改变转换方式,或者添加一种新的转换方式的话,我们只需要修改配置文件就可以了,这样就满足了开闭原则。
在这里插入图片描述

四、接口隔离原则

定义

使用多个专门的接口,而不使用单一的总接口。也就是说客户端不应该依赖那些它不需要的接口。

优点

如果我们使用一个很大的、统一的接口的话,那么他将不能够对客户隐藏那些不需要的行为,如果使用了单一的接口,就好比是给客户提供了定制服务
在这里插入图片描述

怎么应用?

某软件公司开发人员在开发CRM(客户关系管理系统)时,针对客户数据显示模块设计了下面的接口
在这里插入图片描述
那他有哪些职责呢
在这里插入图片描述
该接口包含了很多服务
具体的实现类即使不需要也必须实现其中的全部方法破坏了程序的封装性,客户端看到了不该看到的方法。

换言之,当我们客户端需要使用某一个服务的时候,必须要实现整个大的接口,也就是说这里面即使有我不需要的方法,我也必须要把他实现出来;
并且即使我不需要,我也看到了这些方法,没有很好的做到封装和隐藏,所以这样的设计是不合理的

我们要用接口隔离原则对他进行重构:
我们按照刚才分析出来的四个职责,分别为他定制四个接口
在这里插入图片描述
这样我们就可以根据自己的需求去实现专门的接口,这样的接口隔离就相当于给客户端提供定制服务,客户端(实现类MobileDisplay)也不会出现无用代码
在这里插入图片描述

五、里氏替换原则

定义

所有引用父类的地方必须能透明地使用其子类的对象,话句话说,子类继承父类时不应该改变父类的行为/功能,但可以扩展父类功能(子类可以完全代替父类)

里氏替换原则是针对继承关系进行优化,我们先来想想继承的几个用途:
用作表示两个类之间的共性机制(泛化)
表示一个类是另一个类的特殊形式(特化),子类可以在继承父类的基础上去添加属于自己的属性或方法,子类可以重写父类的方法。

继承的优缺点

优点:实现简单、提高代码重用、提高父类扩展性
缺点:降低代码灵活性、增强了类与类之间的耦合度

什么时候使用继承合适呢?

某家公司里所有的员工都是新员工,每个新员工都有薪水、病假时间和医疗计划。并且有一些适用于新员工的方法,分别为计算税收、计算福利 benefits。
针对该案例我们有个原始设计:
目前新员工这个类里面有三个属性,两个方法
在这里插入图片描述
6个月之后,公司进展顺利。决定每位被公司雇佣了6个月的员工被看做老员工,有额外的福利。这些福利包括牙科医疗计划、休假和公司提供的轿车。
在刚才类的基础上,老员工在新员工基础之上多了属于自己的属性,我们就把老员工当做新员工的子类,除了继承原有的属性和方法之外,我们可以对其中一个方法进行扩展代码
在这里插入图片描述
公司如此成功,以至于新员工需要花5个月的时间来获悉找谁来报销、找谁签采购单、找谁请病假等。公司决定为新员工准备一次介绍课程 course()。
而老员工显然不需要这个课程。老员工的子类就需要去覆盖这个方法,具体表现为“不上该课程”。
在这里插入图片描述
但是里氏替换原则是:子类可以扩展父类功能,但是不能改变父类原有功能,所以目前这种类的结构违反了里氏替换原则

我们用里氏替换原则对他重构设计:
我们把新员工和老员工都当做员工的子类,我们把共同的属性和方法放到员工的父类里面去,这时属于新员工的课程方法由子类去添加成为自己的方法,老员工也可以针对福利的方法去扩展代码
在这里插入图片描述

六、迪米特原则

定义

一个软件实体应当尽可能少的与其他实体发生相互作用;
一个类对自己依赖的类知道的越少越好。
俗话说就是不和陌生人说话

迪米特法则包含两种角色:依赖者与被依赖者。
依赖者只依赖应该依赖的对象
被依赖者只暴露应该暴露的方法或者属性

分析

依赖者:只与直接朋友通信(不要和陌生人说话)
两个对象之间的耦合关系我们称之为朋友,关系通常有:依赖、关联、聚合、组合等
直接朋友关系有(关联、聚合、组合)
被依赖者:暴露尽可能少的信息(最少知识原则)
可用private(私有的)就绝不用protected(受保护的);
可用protected(受保护的)就绝不用public(公有的)

怎么应用?

新学期开堂,老师让课代表清点班级学生人数,以下是老师与学生关系的原始结构设计。
在这里插入图片描述
在原始设计里面教师类不仅要依赖于课代表类还要和所有学生相依赖
很明显有这种设计违反了迪米特法则,老师和学生之间不需要依赖关系,老师只需要和直接朋友相依赖,迪米特法则也叫不和陌生人说话

我们用迪米特法则对他进行重构设计
迪米特法则说:一个软件实体应当尽可能少的与其他实体发生相互作用。(最少知识原则)
这时我们将教师类和学生类之间的依赖关系解除,这时候只需要和直接朋友课代表相依赖,就能满足掌握所有学生信息的目的
在这里插入图片描述

七、合成/聚合复用原则

定义

在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象进行委派,达到复用这些对象的目的。

前提

在面向对象设计中,需要在不同的环境中复用已有的设计和实现

复用的两种方式:
1:继承
通过子类去继承父类 “方法、属性” 完成行为复用
针对继承关系来说:灵活性差、使用环境有限、也叫 “白箱” 复用

2:组合 / 聚合
通过添加 “属性” 完成行为复用
针对组合 / 聚合关系来说:类与类之间的耦合度相对较低、可以选择性的调用成员对象的操作,并且可以在运行的时候动态进行,新对象可以动态的引用与成员对象类型相同的对象,并且这种复用关系支持包装,因为成分对象的内部细节与新对象来说是看不见的,我们也叫黑箱复用

怎么应用?

每个品牌的小轿车价格和外观都不同,通过该案例得出以下原始设计,利用继承完成复用。
想要动态的增加轿车品牌和车的其他表现,这时利用继承会导致代码灵活性很差
在这里插入图片描述

想要动态的增加轿车品牌和车的其他表现,利用组合/聚合怎样进行修改?
在这里插入图片描述
我们用通过对象的组合方式来完成品牌的增加,从而来完成功能的复用,能够在运行的过程中动态的增加行为,使得我们的灵活性、可变性都会提高

总结

面向对象设计的基本原则

单一职责原则(SRP)
类的职责要单一。

“开——闭”原则(OCP)
针对可变因素进行抽象化。

里氏替换原则(LSP)
继承层面、子类型必须能够替换掉他们的父类型。

依赖倒转原则(DIP)
引入抽象模块、针对接口编程。

接口隔离原则(ISP)
合理划分接口。

Demeter法则(LoD)
不要跟陌生人说话、最少知识原则。

合成/聚合复用原则(CARP)
尽量使用组合/聚合/关联、尽量不使用继承。

设计原则之间的关系

开闭原则应用单一职责原则,其关键是抽象

里氏替换原则是开闭原则的补充,是实现抽象的步骤规范

依赖倒置是实现开闭原则的手段

接口隔离原则前提是单一职责原则

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

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

相关文章

对标推特,Threads横空出世,最新Threads账号注册和登录保姆级教程

Meta 正式在全球超过 100 个国家地区应用商店上线 Threads,一款和 Twitter 高度相似的社交软件,并将其定位为 Instagram 的文字对话应用。 Meta 试图以 Threads 吸引那些因马斯克决策而离开了 Twitter 的用户。 在Threads帖文中,扎克伯格向所…

从C语言到C++_24(二叉搜索树)概念+完整代码实现+笔试题

目录 1. 二叉搜索树(BinarySearchTree) 1.1 二叉搜索树的优势和劣势 二叉搜索树的时间复杂度:O(N) 1.2 二叉搜索树的改良 2. 二叉搜索树的实现 2.1 二叉搜索树的定义 2.2 二叉搜索树的插入 2.3 二叉搜索树的查找 2.4 二叉搜索树的删…

(汽车级)TMCS1101A3BQDRQ1、TMCS1101A3UQDRQ1隔离式霍尔效应电流传感器 6mA 8-SOIC

TMCS1101/TMCS1101-Q1精密隔离电流传感器是电隔离霍尔效应电流传感器&#xff0c;能够进行直流或交流电流测量&#xff0c;具有高精度、出色的线性度以及温度稳定性等特性。低漂移、温度补偿信号链在整个器件温度范围内具有<1.5%满量程误差。输入电流流经内部1.8mΩ导体&…

只需2行python代码,轻松将PDF转换成Word

1. pdf2docx功能 - 解析和创建页面布局- 页边距- 章节和分栏 (目前最多支持两栏布局)- 页眉和页脚 [TODO]- 解析和创建段落- OCR 文本 [TODO] - 水平&#xff08;从左到右&#xff09;或竖直&#xff08;自底向上&#xff09;方向文本- 字体样式例如字体、字号、粗/斜体、颜色…

什么是V2G充电技术?

据权威数据统计&#xff0c;截止2020年&#xff0c;我国纯电动汽车保有量已经达到400万辆。随着电动汽车保有量的快速增长&#xff0c;对电网会有一定的影响&#xff0c;电力容量需求增大&#xff0c;加剧用电峰谷差&#xff0c;对电网的冲击大&#xff0c;影响居民正常生活。这…

C#核心知识回顾——11.各数据集合的汇总区分、委托、事件

变量: 无符号 byte正8位 ushort正16位 uint正32位 ulong正64位 有符号 sbyte8位 short16位 int32位 long64位 浮点数 float double decimal 特殊 char bool string 复杂数据容器: 枚举enum 结构体struct 数组(一维、二维、交错) [] [,] [][] 类 数据集合&#xff1a;…

leetcode--杨辉三角(C、C++)

文章目录 1.C实现2.C实现 1.C实现 #include<stdio.h> #include<stdlib.h> #include<assert.h>int** generate(int n, int* rnum_row, int** rnum_row_ele) {//*rnum_row-->num_row&#xff1a;杨辉三角行数*rnum_row n;//*rnum_row_ele-->num_row_el…

深度学习笔记之Transformer(五) Position Embedding铺垫:Word2vec

深度学习笔记之Transformer——Position Embedding铺垫&#xff1a;Word2vec 引言回顾&#xff1a;关于词特征表示的 One-hot \text{One-hot} One-hot编码目标函数构建关于语料库与任务目标似然函数构建 Word2vec \text{Word2vec} Word2vec模型结构重点总结 引言 在Transforme…

Zabbix“专家坐诊”第198期问答汇总

问题一 Q&#xff1a;请问一下&#xff0c;自带的思科SNMP交换机模板&#xff0c;怎么不监控down的接口&#xff1f; A1&#xff1a;这种一般在自动发现规则里加个过滤器&#xff0c;过滤出IFSTATUS匹配(1|3)的就能实现只发现up的端口了。 A2&#xff1a; 在“Items”页面&a…

Unity | 从建模到蒙皮动画的整个过程

目录 一、顶点数组、索引数组及UV数组 二、Mesh、MeshFilter、MeshRenderer及SkinnedMeshRenderer 1. Mesh 2. MeshFilter 3. MeshRenderer 4. MeshRenderer与SkinnedMeshRenderer&#xff08;蒙皮网格&#xff09; 三、Unity中相关组件 1. mesh和material 2. sharedM…

【微信小程序创作之路】- 小程序项目组成(初创小程序)

【微信小程序创作之路】- 小程序项目组成&#xff08;初创小程序&#xff09; 提示&#xff1a;第二章 初创小程序&#xff0c;讲解小程序项目组成 文章目录 【微信小程序创作之路】- 小程序项目组成&#xff08;初创小程序&#xff09;前言一、下载安装小程序微信开发者工具二…

Python multiprocessing 多进程

在multiporcessing中&#xff0c;通过新建Process对象创建进程&#xff0c;然后用start()方法调用它。Process与threading.Thread类似。如下是一个简单的例子&#xff1a; from multiprocessing import Processdef f(name):print(hello ,name)if __name__ __main__:p Proces…

2D和3D双管齐下才是王道?KAUST联合Snap、VGG提出单张图像三维重建的Magic123框架

在最近的AIGC社区中&#xff0c;3D视觉生成领域越来越受到广泛的关注&#xff0c;以神经辐射场&#xff08;NeRFs&#xff09; 为基础的深度渲染网络向大家展示了非常惊艳的三维效果。可是&#xff0c;NeRFs需要大量的多视角图片作为监督&#xff0c;因而从单张2D图像进行3D重建…

昆仑万维的“天工”能否改变人工智能应用的格局?

在人工智能领域&#xff0c;昆仑万维公司近日引发了广泛关注&#xff0c;发布了名为“天工”的大语言模型。这一新的技术突破引发了人们对于人工智能应用格局是否会被改变的讨论。随着昆仑万维进军大型语言模型市场&#xff0c;人们开始思考&#xff0c;“天工”能否成为人工智…

面部表情动画数据捕捉利器——AH表情捕捉头盔

在游戏制作、电视广告、影视动画制作中&#xff0c;逐渐开始采用面部捕捉头盔进行采集表情面部数据。广州虚拟动力推出的AH表情捕捉头盔&#xff0c;能够轻松创建实时逼真的面部动画&#xff0c;搭配广州虚拟动力的动作捕捉系统VDMocap Studio Plus&#xff0c;能够自动运算出表…

第八章:怎样远程连接+远程连接常用工具+Teamviewer详解

目录 一、什么是远程连接 二、为什么需要远程连接 三、常用的远程连接工具 四、Teamviewer 一、什么是远程连接 远程连接就是在远程连接另外一台计算机。当某台计算机开启了远程桌面连接功能后我们就可以在网络的另一端控制这台计算机了&#xff0c;通过远程桌面功能我们可…

基于Java校园二手物品交易平台设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

hive函数dayofweek的奇怪用法

hive函数dayofweek的奇怪用法 1.单独使用 select dayofweek(2023-07-03); 周一 2 select dayofweek(2023-07-04); 周二 3 select dayofweek(2023-07-05); 周三 4 select dayofweek(2023-07-06); 周四 5 select dayofweek(2023-07-07); 周五 6 select dayofweek(2023-07-08); …

VIO在ARM上的加速(2)- Neon

VIO在ARM上的加速&#xff1a; VIO在ARM上的加速&#xff08;1&#xff09;- ARM加速基础 VIO在ARM上的加速&#xff08;2&#xff09;- Neon VIO在ARM上的加速&#xff08;3&#xff09;- Neon在VIO中的应用 1 NEON的概述 ARM 处理器中使用的高级 SIMD 扩展的实现称为 NE…

【数据结构与算法】魔王语言解释(C/C++)

实践要求 1. 问题描述 有一个魔王总是使用自己的一种非常精炼而抽象的语言讲话&#xff0c;没有人能听懂。但他的语言是可以逐步解释成人能懂的语言的&#xff0c;因为他的语言是由以下两种形式的规则由人的语言逐步抽象上去的: 形式一 α → β 1 β 2 . . . β m \alpha \…