【面向对象】面向对象七大原则

设计模式

设计模式是什么?

设计模式是一种针对于反复提出问题的解决方案,是经过长时间经验和试错而总结出来的一套业务流程;

其目的是为了提高代码的可重用性和可维护性,让代码更容易让人理解,保证代码可靠性;

设计模式所担当的角色和位置

设计模式与算法和软件系统的架构所处在的位置不同

**算法:**是为了解决一套困难及问题所完成的,是一系列解决问题的清晰指令;

**设计模式:**常见问题的通用思想/模版,一种高程度的抽象概念;

软件架构:在知道大型软件系统的各个方面的设计,是凌驾于设计模式之上的;

面向对象

面向对象是什么?

面向对象是一种结构化的编程方法,它通过封装、继承、多态和抽象等特性,使得代码更加模块化可扩展,并且更容易维护。

模块化思想,可扩展性的思维模式,就是设计模式的一种基本思想。

面向对象设计原则是学习设计模式的基础,设计模式的本质也便是面向对象设计原则

每种原则都包含着一些设计思想,可以从不同的角度去提升软件中的结构;在进一步前进,就是重构;

重构代码,力求在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。

UML

UML(统一建模语言)是系统设计中捋清思路所不可获缺的内容;

结构型图

  1. 类图(Class Diagram):系统中类的静态结构,包括类的属性、方法以及类与类之间的关系,如关联、继承、实现等。

  1. 对象图(Object Diagram):是类图的实例,展示类的对象在某一时刻的状态以及对象之间的关系

画板

  1. 组件图(Component Diagram):描述系统中组件的物理结构以及组件之间的依赖关系,组件可以是代码模块、可执行文件等。

画板

  1. 部署图(Deployment Diagram):显示系统的物理部署,包括硬件设备、软件组件在这些硬件上的部署情况。

  1. 包图(Package Diagram):用于组织和管理模型元素,展示包与包之间的依赖关系,包可以包含类、组件等元素。

画板

行为型图

  1. 用例图(Use Case Diagram):从用户的角度描述系统的功能,展示系统的参与者(用户或外部系统)与系统提供的用例(功能)之间的关系。

画板

  1. 活动图(Activity Diagram):描述系统中各种活动的执行流程,类似于流程图,可用于展示业务流程、算法步骤等。

  1. 状态图(State Diagram):展示对象在其生命周期内的各种状态以及状态之间的转换,适用于描述具有状态变化的对象行为

画板

  1. 序列图(Sequence Diagram):按时间顺序展示对象之间的交互,强调对象之间消息传递的顺序。

通信图(Communication Diagram):也用于展示对象之间的交互,但更侧重于对象之间的连接关系和消息传递,不强调时间顺序。

画板

UML类图的各种关系

  1. 关联(Association)
    • 含义:表示类之间的一种静态结构,是一种比较 “强” 的关系,比如对象 B 是对象 A 的成员对象。
    • 表示方式:通常用一条实线表示。 动物->鸟
  2. 继承(泛化,Generalization)
    • 含义:用于表示子类与父类之间的关系。子类拥有父类的所有功能。
    • 表示方式:用实线 - 空心箭头,箭头指向基类医生->人
  3. 实现(Realize)
    • 含义:是一种类与接口之间的关系。
    • 表示方式:用虚线 - 空心箭头,箭头指向接口。 手机 -> WiFi功能 <<实现>>
  4. 依赖(Dependency)
    • 含义:描述的是某个类的对象在运行期间,可能会用到另一个对象,这是一种比较 “弱” 的关系,不同于关联,比如类 A 成员方法的形参是类 B 的实例对象。
    • 表示方式:用虚线箭头表示。
  5. 组合(Composition)
    • 含义:是一种整体与部分的关系,且部分不能离开整体而单独存在,是一种比聚合还强的关系。
    • 表示方式:带实心菱形的实线,菱形指向整体。
  6. 聚合(Aggregation)
    • 含义:也是描述整体与部分的关系,且部分可以离开整体而单独存在,区别于组合。
    • 表示方式:带空心菱形的实心线,菱形指向整体

面向对象的七大设计原则

总述

  1. 面向对象设计原则
设计原则名称设计验证简介
单一职责原则(Single Responsibility Principle,SRP)类的职责要单一,不能把太多的职责放到一个类中;
开闭原则(Open-Closed Principle,OCP)软件实体对扩展是开放的,但修改是关闭的。在不修改原来实体功能的基础上扩展功能;(代理模式
里式替换原则(Liskov Substitution Principle LSP)在软件系统中,一个可以接受基类的地方必然要可以接受一个子类对象;
依赖倒转原则(Dependency Inversion Principle DIP)只针对于抽象层编程,不要针对于具体的类编程;(DI 依赖注入
接口隔离原则(Interface Segregation Principle ISP)使用多个专门的接口来取代一个统一的接口;
合成复用原则(Composite Reuse Principle CRP)在复用功能时,应当尽量多的使用组合和聚合关系,尽量少的使用继承关系;
迪米特法则(Law of Demeter LoD)一个软件实体对其他实体的引用越少越好,或者说两个类不必彼此之间直接通讯,那么这两个类不应当直接发生相互作用,而是引入第三者进行直接交互;

「设计模式」理解面向对象的七大设计原则,消除代码中的坏味道

单一职责原则

定义:
  1. 单一职责原则是最简单的面向对象设计原则,用于控制类粒度的大小;它建议一个对象应该只包含单一的职责。
  2. 一旦某个类承担的职责越多,相当于这些职责被耦合在同一个类中,所以它能被复用的可能性就越小
  3. 单一职责原则旨在实现高内聚、低耦合,在很多代码重构的手法中都能见到它的身影,虽然思想简单但是却最难运用,因为只有当你有较强的分析能力后,才能将一个耦合度极高的类分离成几个单独的职责明确的类。
分析
  1. 原始方案

  • 实现功能:初始化页面、获取数据库连接、根据账号密码获取User数据
  1. 重构方案

  • 拆离所有的业务逻辑,封装内容,只保留一个main方法;
  • 拆分一:在main中导入LoginForm.class执行,后续逻辑,初始化功能的逻辑在该Class的执行;;
  • 拆分二:分析业务结构,关联数据库,查询数据,封装数据库持久层的内容UserDao,只提供数据 ,进行查询,不进行DB交互;
  • 拆分三:DB交互功能单独封装一个实体类:DButil

开闭原则

定义

一个软件实体应当对扩展开放,对修改关闭。也就是说设计的模块能在不被修改源代码的前提下,对其进行扩展。

开闭原则的切入点:将系统的可变因素封装并抽象到上层。

分析
  1. 原始方案

  • 问题点: 如果界面类 LoginForm 需要将圆形按钮 CircleButton 改为矩形按钮 RectangleButton,那么不仅要修改 LoginForm 中的按钮类的名字,还要修改 display() 方法适配修改后的按钮。
  1. 重构方案

  • 根据开闭原则,抽离出来AbstractButtonCircleButtonRectangleButton 都继承AbstractButton的功能,然后在追加自己的内容;
  • 通过配置文件或者set注入的方式,在LoginForm想要增加新的的按钮;
  • 修改功能也是同样的道理,使用一个切入点切入,在不动根本的情况下修改之前的内容;
  • CircleButtonRectangleButton 都继承AbstractButton的功能,所以可以使用AbstractButton的原则上也可以使用继承自他的对象;

里式替换原则

定义
  1. 里氏替换原则要求所有引用基类(父类)的地方必须透明地使用其子类的对象。
  2. 开闭原则的核心是对系统进行抽象化,并且从抽象化导出具象化从抽象化到具象化的过程则需要里氏替换原则的指导。
分析
  1. 原始方案

在实现开闭原则的前提下,需要再对其枪械的种类进行扩展,扩展玩具手枪 ToyGun 类的原始设计方案如下:

  1. 引用里氏替换原则后

  • ToyGun虽然 继承于Gun,但是是不能执行 killEnemy的,所有是有问题的,不符合 里式替换原则
  • ToyGun抽象出来,聚合到 Toy下;
  • Soldier完成 kellEnemy是需要依赖 Gun而不是Toy

依赖倒转原则

定义

简单理解依赖倒转原则,就是要针对接口编程,不要针对实现编程。

依赖倒转原则旨在通过对接口编程颠覆传统的过程型系统:高层依赖低层。其实就是<font style="color:rgb(37, 43, 58);">IOC</font>的控制反转,可以联系Spring的IOC依赖注入的方式。

分析
  1. 原始

  • 写一个Driver执行BenzBMW
  • 加一个Audi需要再写一个Audi;长期以往;
  1. 使用依赖倒转原则

  • 反正实行的都是ICar,使用的一样的方法,抽象出来ICar接口,IDriver执行ICar
  • BenzBMW实现 ICar
  • Driver实现 IDriver
  • 以上,我们就不需要反复修改我们的代码逻辑,只需要通过注入的方式就可以;譬如,注入BMWDriver执行BMW

接口隔离原则

定义
  1. 使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。
  2. 在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供用户需要的行为,而隐藏用户不需要的行为。
分析
  1. 原方案
  2. 对应后方案
  • 无论是使用一个实现类(如图)还是三个实现类,对于 ClientA 都只能访问它对应的方法,无法访问与之业务无关的另外两个,因为它们是针对抽象接口进行编程的。

合成复用原则

定义

尽量使用对象组合,而不是继承来达到复用的目的

合成复用原则(又称组合 / 聚合复用原则)也是一条相当重要的原则,为了降低系统中类之间的耦合度,该原则倡导在复用功能时多使用关联关系,少使用继承关系

对比一下两种复用机制:

  • 继承复用:子类只需覆盖父类方法,但关键问题在于父类的内部细节完全暴露给子类,破坏系统的封装性;而且一旦超类发生变化,子类也不得不随之变化,使得子类不够灵活
  • 组合 / 聚合复用:由于组合 / 聚合是将其他对象 B 转化为某对象 A 的成员对象,所以其他对象 B 的内部实现细节对于 A 是完全不可见的,实现了系统的封装性。

链接:https://juejin.cn/post/7072521978095075358

分析
  1. 原方案
  • DBUtil用于连接数据库,提供getConnection()方法连接DB获取数据库返回对象,两个实体类都需要调用DBUtil.getConnection();,使用继承实现的话 这样就会出现继承服用;
  • 在执行时,会调用DBUtil.getConnection();,内容的所有数据库配置等参数都会被执行时发现;
  • 如果更改可连接方式或者数据池,原来的DBUtil的方法就不能够被使用了,我们就只能在写一个DBUtilR,或者继承之后再重写一遍DBUtil的方法,这样就违背了前面的开闭原则,整个逻辑就会显得扩展性极差
  1. 修改后
  • 图解的我理解的不是很清晰,简要概述下自己的思想
  • 不要多用继承,可以在所需的方法中,将要实现的类 引用为所需要的对象,以防止出现上述我所描述的那种现象;
  • 在DBUtil中,我们创建 JDBCUtil方法,PoolUtil方法,··· ··· 在使用DBUtil时,我们不用继承,在方法中New一个新的对象DBUtil,或者new一个继承自DBUtilJDBCUtil/PoolUtil,将其作为我们持久层方法的一个引入的对象,这样我们再进行使用的时候,只会对我们只调用的自己的方法进行使用;

迪米特法则

定义

迪米特法则指导软件实体应当尽可能少地与其他实体发生相互作用。

又称最少知识原则,不要与不认识的人陌生对象,只自己相关的对象打交道;

朋友的定义范围:

  • 当前对象本身
  • 依赖对象(以参数形式传出成员方法的对象)
  • 当前对象的成员对象
  • 成员对象的元素(成员对象是集合的情况,元素可能也是对象)
  • 当前对象所创建的对象

当前对象与 ”陌生人“ 保持着微乎其微的依赖关系,它们之间仍是耦合状态,这就需要第三方对象 ”朋友“ 来转发调用二者之间的通信,以降低系统的耦合度,使得类与类之间保持松散的耦合关系;但同时也会降低系统不同模块间的通信效率。高内聚,低耦合 很重要!!

分析
  1. 原方案

public class Someone {private Stranger stranger = new Stranger();public void operation1(Friend friend) {Stranger stranger = friend.provideStranger();stranger.operation3();}
}

Someone 类需要调用 ”陌生人“ 的 operation3() 方法,于是通过 ”朋友“ 的 provideStranger() 方法获取到了 Stranger 对象,然后调用该对象的 operation3()

看似很常见且合理,因为平常我们也是像这样编写代码的,但常见就一定合理吗?其实 SomeoneStranger 之间存在一层弱弱的依赖关系,因为 Friend 提供的 Stranger 对象还是在 Someone 方法中进行了调用,仍然存在耦合,违背了迪米特法则的指导思想

  1. 重构方案

public class Someone {public void operation1(Friend friend) {friend.forward();}
}public class Friend {private Stranger stranger = new Stranger();public void forward() {stranger.operation3();}
}

通过 Friend 的转发调用,使得 SomeoneStranger 解耦,一旦 Stranger 被替换掉,也不会影响 Someone 源代码的修改。

以上 针对于「设计模式」理解面向对象的七大设计原则,消除代码中的坏味道 的学习,思维模型的学习,受用无穷。

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

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

相关文章

《计算机“十万个为什么”》之 面向对象 vs 面向过程:编程世界的积木与流水线

《计算机“十万个为什么”》之 面向对象 vs 面向过程&#xff1a;编程世界的积木与流水线 &#x1f916; 想象你要造一辆汽车&#x1f527;&#xff1a; 面向过程 按手册一步步拧螺丝&#xff1a;拧紧螺栓A → 安装轮胎B → 焊接车架C 面向对象 召唤汽车人战队&#xff1a;引…

Visual Studio Code (VSCode) 的常用快捷键

Visual Studio Code (VSCode) 的常用快捷键可极大提升开发效率。以下是分类整理的 **核心快捷键**&#xff08;基于 **Windows/Linux** 系统&#xff0c;macOS 用户将 Ctrl 替换为 Cmd&#xff0c;Alt 替换为 Option&#xff09;&#xff1a;⚡ 基础操作快捷键功能Ctrl N新建文…

vite面试题及详细答案120题(01-30)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Cesium学习(一)-基础

Cesium是一个开源的JavaScript库&#xff0c;专门用于创建3D地球和地图可视化。它在GIS、航空航天、城市规划等领域有广泛应用。 Cesium核心特性3D地球可视化 基于WebGL的高性能3D渲染支持全球地形和影像数据准确的地球模型&#xff08;WGS84椭球体&#xff09;多维数据支持 时…

饿了么招java开发咯

研发工程师-JAVA/Golang&#xff08;岗位信息已经过jobleap.cn授权&#xff0c;可以在CSDN发布&#xff09;饿了么 杭州收录时间&#xff1a; 2025年08月05日职位描述1、参与基础软件的设计、开发和维护&#xff0c;如分布式中间件、DevOps平台、应用监控系统等&#xff1b; 2…

java web 未完成项目,本来想做个超市管理系统,前端技术还没学。前端是个简单的html。后端接口比较完善。

代码结构 超市管理系统/├── src/ │ ├── com/ │ │ └── zhang/ │ ├── documents.txt │ ├── documents_detail.txt │ ├── goods.txt │ ├── order.txt │ ├── order_detail.txt │ ├── role.txt │ ├── tb_test.txt │ …

R语言基础图像及部分调用函数

R语言基础图像及部分调用函数 散点图 散点图是将所有的数据以点的形式展现在直角坐标系上&#xff0c;以显示变量之间的相互影响程度&#xff0c;点的位置由变量的数值决定&#xff0c;每个点对应一个 X 和 Y 轴点坐标。 散点图可以使用 plot() 函数来绘制 例子 x<-c(10,40)…

自由学习记录(77)

官方模版、、都不用了&#xff0c;记得之前用gitextension 的时候也好像有这种问题&#xff0c;也不知道怎么回事 用自己的就行了 网上说什么都没用&#xff0c;还是要自己老实写&#xff0c;配上截图工具截屏目录直接转文字过去&#xff0c;其实字都不要打多少的 一张很深刻…

运动想象 (MI) 分类学习系列 (18) : MSVTNet

运动想象分类学习系列:用于基于脑电图的运动图像解码的多尺度视觉转换器神经网络 0. 引言 1. 主要贡献 2. 方法![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/65a03fcd4a9144f6a7324b0969fd9d4e.png#pic_center) 3. 结果 3.1 脑电图数据预处理 3.2 解码性能比较 3.3…

Spring 03 Web springMVC

Springboot 常用 Spring MVC 实现 web 服务。 Spring MVC 请求处理流程图片来自《Spring 实战第四版》 浏览器请求首先被交给 DispatcherServlet 前端控制器。 DispatcherServlet 查询处理器映射以决定将请求发送给哪个控制器。控制器处理业务逻辑后&#xff0c;向 DispatcherS…

大厂面试题

线程池的状态?回答:running->shutdown->stop->tidyng->TERMINATED 线程池状态怎么流转2. 回答:变成shutdown&#xff0c;执行shutdown()函数变成stop&#xff0c;执行shutdownnow函数 变成tining&#xff0c;所有任务已处理完 变成TERMINATED&#xff0c;线程池调…

达芬奇31-40

快捷键C鼠标左键拖拽到节点上 A鼠标左键拖拽节点 复制到另一个图层上Raw素材太哦调整为log方便调色磨皮中间调向左磨皮,向右变老找到丢失的高光磨皮后脸部高光消失,或不明显,此时用亮度吸管工具找到脸部的高光,拉高中灰和亮部的Y值质感纹理增强器Tiny,Fine高频细节(脸部)增强或…

dify

一、SVG Logo Design ### 任务 我希望你充当图像生成的提示生成器。 ### 任务描述 你的工作是提供详细且富有创意的描述&#xff0c;以激发 AI 生成独特而有趣的图像。请记住&#xff0c;格式应遵循以下一般模式&#xff1a; <主要主题>, <主要主题的描述>, <背…

Mysql 实战问题处理速通

文章目录创建账号和授权查询没有主键的表统计每个库大小前十张大表清理日志表Prepared statement needs to be re-preparedxtrabackup 问题锁问题处理快速处理查询事务等待和阻塞情况innodb_trxprocesslistdata_locksdata_lock_waitsmetadata_locksevents_statements_current其…

如何测量滚珠花键的旋转方向间隙?

测量滚珠花键的旋转方向间隙需要使用适当的工具&#xff0c;通常情况下&#xff0c;可以使用游标卡尺或外径卡尺进行测量。这些工具可以准确地测量间隙的宽度和深度&#xff0c;并且可以轻松地记录测量结果。手动检测法&#xff1a;将滚珠花键固定在支架上&#xff0c;确保其可…

Android AppSearch 深度解析:现代应用搜索架构与实践

一、AppSearch 概述1.1 什么是 AppSearchAppSearch 是 Android Jetpack 组件库中的一个现代化本地搜索框架&#xff0c;于 Android 12 (API level 31) 引入&#xff0c;旨在为 Android 应用提供高效、可靠的本地数据索引和搜索能力。与传统的 SQLite 搜索方案相比&#xff0c;A…

使用公众号的消息模板给关注用户发消息

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

【盘古100Pro+开发板实验例程】FPGA学习 | 3X3图像矩阵生成 | 图像实验指导手册

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 1. 实验简介 实验目的&#xff1a; 实现 3X3 图像矩阵对应 9 个像素点图像数据的读取。 实验环境&#xff1a; Wind…

【通用视觉框架】基于OpenCvSharp+WPF+YOLO开发的仿VisionMaster的通用视觉框架软件,全套源码,开箱即用

【通用视觉框架】基于OpenCvSharpWPFYOLO开发的仿VisionMaster的通用视觉框架软件&#xff0c;全套源码&#xff0c;开箱即用 基于OpenCvSharp、WPF和YOLO的组合&#xff0c;构建一个兼具图像处理能力、可视化交互和实时检测的工业级视觉框架。其核心是将底层算法与上层界面无…

微信小程序转Vue2组件智能提示词

角色 小程序转Vue2组件工程师&#xff08;ElementUI专精&#xff09; 核心能力 技术专长&#xff1a;作为世界顶尖前端工程师&#xff0c;专注于将小程序组件&#xff08;.wxml/.wxss/.js/.json&#xff09;精准转换为Vue2ElementUI组件&#xff0c;转换逻辑零偏差&#xff0c;…