面向对象设计原则概述

news2024/11/18 7:40:07

面向对象设计原则概述

软件的可维护性和可复用性

软件工程和建模大师Peter coad认为,一个好的系统设计与应该具备如下三个性质

可扩展性

灵活性

可插入性

image-20230101185202111

软件的可维护性和可复用性

  • 软件的复用和重用拥有众多优点,如可以提高软件的开发效率,提高软件质量,节约开发成本,恰当地服用还可以改善系统发的可维护性

  • 在面向对象设计服用的目标在于实现支持可维护性的复用

  • 在面向对象的设计里面,可维护性复用都是以面向对象设计原则为基础的,这些设计原则首先都是复用的原则,准学这些设计原则可以有效地提高系统的复用性,同时提高系统的可维护性

    image-20230101185337252

软件的可维护性和可复用性

面向对象设计原则和设计模式也是对系统进行合理重构的指南针,重构是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。

image-20230101193023940

面向对象设计原则简介

常用的面向对象设计原则包括7个,这些原则并不是孤立存在的,他们相互依赖,相互补充。

设计原则名称设计原则简介重要性
单一职责原则类的职责要单一,不能将太多的职责放在一个类中****
开闭原则软件实体退扩展是开发的,但对修改是关闭的,即在不修改个软件实体的基础上去扩展其功能*****
里氏代换原则在软件系统中,一个可以接受基类对象的地方必然可以接受子类对象****
依赖倒转原则要针对抽象层编程,而不要针对具体类编程*****
接口隔离原则使用多个专门的接口来取代一个统一的接口**
合成复用原则在系统中应该尽量多使用组合和聚合管理关系,尽量少使用甚至不使用继承关系****
迪米特法则一个软件实体对其他实体的应用越少越好,或者说如果两个类不必必测直接通信,不那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互***

单一职责原则

单一职责原则定义如下下:

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

另一种定义方式如下:就一个类而言,应该仅有一个引起它变化的原因

单一职责原则分析

  • 一个类或者大到模块,小到方法,承担的职责越多,他被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责偶合在一起,当其中一个职责变化时,可能会影响其他职责的运作
  • 类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,行为之者通过其方法来体现
  • 单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计院人员发现类的不同职责并将其分离,而发现类的多重职责需要设设计人员具有较强的分析设计能力和相关重构经验。

单一职责原则

sunny软件公司开发人员针对某CRM(客户关系管理)系统中客户信息图形统计模块提出了如图1所示初始设计方案

image-20230101194241947

CustomerData类承担了太多的职责, 即包含与数据库相关的方法,有办函与图表生成和显示相关的方法。

如果其他类中也需要连接数据库或者使用findCustiners()方法查询客户信息,则难以实现代码的重用。无论是修改数据库连接方式还是修改图标显示方式都需要修改该类,他不止一个引起他变化的原因,违背了,违背了单一职责原则。

image-20230101194516613

(1) DBUtil: 负责连接数据库, 包含数据库连接方法getConnection();

(2) CustomerDAO**:** 负责操作数据库中的Customer表, 包含对Customer表的增删改查等方法, 如findCustomers();

(3) CustomerDataChart: 负责图表的生成和显示, 包含方法createChart()和displayChart()

image-20230101194527719

练习

某基于java的C/S系统的登录功能通过如下登录类实现

image-20230101194620387

先使用单一职责原则对其进行重构

image-20230101194650442

开闭原则

开闭原则定义如下

一个软件实体应当对扩展开放,对修改关闭,也就是说在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。

开闭原则是面向对象的可复用设计的第一会基石

image-20230101195004910

image-20230101195014359

任何软件都需要面临一个很重要的问题,他们的需求会随时间的推移而发生变化,当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。

image-20230101195123451

image-20230101195127559

小宋参加工作不久,买了套小房子,房间里有点灯,他希望设计一个智能控制器控制电灯的开馆

image-20230101195216130

image-20230101195243234

小宋后来又陆续买了很多电器,他希望智能控制器都能控制这些 电器开关

image-20230101195309463 image-20230101195321973
Class 控制器{
void 启动(){.打开();
电视.打开();--改动点1
洗衣机.打开();--改动点4
计算机.打开();--改动点7
}
void 停止 (){.关闭();
电视.关闭();--改动点2
洗衣机.关闭();--改动点5
计算机.关闭();--改动点8
}
灯
电视  --改动点3
洗衣机 --改动点6
计算机 --改动点9
}

image-20230101195416335

OCP的关键在于抽象

  • 抽象技术:Abstract class Interface
  • 抽象遇见了可能的所有扩展(闭)
  • 由抽象可以随时导出新的类(开)

image-20230101195514150

使用开闭原则步骤

  1. 在变化的需求中提供共性、制定抽象标准
  2. 具体实现抽象标准
  3. 让软件主体依赖抽象标准

image-20230101195623132

image-20230101195629937

image-20230101195636610

image-20230101195643827

image-20230101195745478

image-20230101195752205

image-20230101195758146

image-20230101195803019

超市收银

image-20230101195822261

image-20230101195837530

image-20230101195931914

收银机设计是否真的完全开闭了

Class 收音

image-20230101200101281

日常生活中有哪些软件系统可以使用开闭原则

移动公司花费系统

image-20230101200156661

image-20230101200208607

image-20230101200218353

里氏代换原则

LSP(Liskov Substitution Principle)在软件中如果能够使用基类对象,那么一定能够使用其子类对象

image-20230101200333981

里氏代换原则分析

喜欢动物–>喜欢猫,因为猫是动物

我喜欢动物,那我一定喜欢猫,因为猫是动物的子类;但是我喜欢猫,不能据此推定我喜欢动物,因为我并不喜欢老鼠,虽然他也是动物

image-20230101200454552

在sunny软件公司开发的CRM系统中,客户可以分为VIP客户和普普通客户两类,系统需要提供一个发送EMAIL的功能,原始设计方案如所示

image-20230101200711228

无论是普通客户还是vip客户,发送邮件的过程都是相同的,也就是说

也就是说两个send方法中的代码重复,而且在本系统可能还将增加新类型的客户,代码修改范围比较大。

使用里氏代换原则对其进行重构

可以考虑增加一个新的抽象客户类,而降CommonCustomer和VIPCustomer类作为其子类,邮件发送类EmailSender类针对抽象客户类Customer编程。

image-20230101201243792

依赖倒装原则

实现“开-闭“原则的关键是抽象化,并且从抽象化到处具体化实现。如果开闭原则 是面向对象设计的目标的话,依赖倒转原则就是这个面向对象涉设计的主要机制

依赖倒转原则讲得是:要依赖与抽象,不要依赖与具体。

传统的依赖关系

传统的过程性系统的设计方法倾向于使高层次的模块依赖于低层次的模块;抽象层次依赖与具体层次。依赖倒转原则是要把这个错误的依赖关系到转过来,这就是依赖倒转原则的来由。

image-20230101201511754

image-20230101201520947

符合DIP的系统

image-20230101201550204

image-20230101201556036

依赖倒转原则定义

依赖倒转原则(Dependence Inversion Principle,Dip)的定义如下:高层模块不应该依赖底层模块,他们都应该以来抽象,抽象不应该依赖于细节,细节应该依赖于抽象。

另一种表述为:要针对接口编程, 不要针对实现编程。‘

依赖倒转原则分析

类之间的耦合

  • 0耦合的关系
  • 具体耦合的关系
  • 抽象耦合的关系

依赖倒转原则要求客户端依赖于抽象耦合,以抽象方式耦合是依赖倒转原则的关键

image-20230101204644907

Sunny软件公司开发人员在开发某CRM系统时发现,该系统经常需要将存储在TXT或EXCEL文件中的客户信息转存到数据库中,因此需要进行数据格式转换,在客户数据操作类将调用数据格式转换类的方法实现格式转换和数据库插入操作,出是设计方案结构如所示

image-20230101204809589

设计方案存在一个非常严重的问题,由于每次转换数据时数据来源不一定相同,因此需要更换数据转换类,如有时候需要将TXTDataConvertor改为ExcelDataConvertor,此时,需要修改CustomerDao的源代码,而且在引并使用新的数据转换类时也不得不得修改CUSTOMERDaode源代码,系统扩展性较差,违反了开闭原则,现需要对该方案进行重构。

image-20230101205154192

由于CUSTOMERDAO针对具体数据转换类编程,因此在增加新的数据转换类或者更换数据转换类时都不得不修改CustomerDao的源代码,,我们可以通过引入抽象数据转换类解决该问题,在引入抽象数据转换类DataConvertor之后,Customer针对抽象类DataConvertor编程,而将具体数据转换类名存储在配置文件中,符合依赖倒转原则。

接口隔离原则

接口隔离原则(ISP)的定义如下

客户端不应该依赖那些他不需要的接口

另一种定义如下:

一旦一个接口太大,则需要将他风格成一些更细小的接口,使用该接口的客户端仅需指导与之相关的方法即可

接口隔离原则是指使用多个专门的接口,而不使用单一的总接口,,每一个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干。

  • 一个接口就只代表一个角色,每个角色都有它特定的一个接口,此时这个原则可以叫做角色隔离原则
  • 接口仅仅提供客户端需要的行为,即所需的方法,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。

接口隔离原则分析

  • 使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。
  • 可以在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供用户需要的行为,而隐藏用户不需要的行为。

实例说明

下图展示了一个拥有多个客户类的系统,在系统中定义了一个巨大的接口AbstratctService来服务所有的客户类,可以使用接口隔离原则对其进行重构。

image-20230101210246996

image-20230101210315002

合成复用原则

合成复用原则定义如下(CRP)又称为组合/聚合复用原则,其定义如下

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

合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用已有功能的目的,简言之:要尽量使用组合/聚合关系,少用继承。

合成复用原则分析

在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承。

  • 继承复用,实现简单,易于扩展。破坏系统的封装性,从基类继承而来的实现是今天的,不可能在运行时发生改变,没有足够的灵活性,只能在有限的环境中使用(白箱复用)
  • 组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行(“黑箱复用”)

某教学管理悬停部分数据库访问类设计如图所示

image-20230102061350093

如果需要更换数据库连接方式,如原来采用jdbc连接数据库,则需要修改DBUtil类源代码,如果StudentJDBC链接,但TeacherDAO采用连接池链接,则需要增加一个新的DBUtil类并修改StudentDao或者teacherDao的源代码,使之及诚信的数据库连接类,这将违背开闭原则,系统扩展性较差

image-20230102061730466

迪米特法则

迪米特法则又称为最少知识原则,她有多重定义方法,其中几种电信定义如下

  1. 不要和陌生人说话
  2. 只与你的直接朋友通信
  3. 每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位

简单来说,迪米特法则就是指一个软件实体应当尽可能少的与其他实体发生相互作用,这样,当一个模块修改时就会尽量少的影响其他的模块,扩展会相对容易,这是对软件实体之间通信的限制,他要求限制软件实体之间的通信的宽度和深度。

迪米特法则分析

在迪米特法则中,对于一个对象,其朋友包括以下几类

  1. 当前对象本身(this)
  2. 以参数形式传入大当前对象方法中的对象
  3. 当前对象的成员对象
  4. 如果当前对象的成员对像是一个集合,那么集合中的元素也是朋友
  5. 当前对象所创建的对象

任何一个对象,如果满足上面的条件之一,就是当前对象的朋友,否则就是陌生人。

实例说明

某系统界面类(如form1,form2)与数据访问类如dao1,dao2等类之间的调用关系较为复杂

image-20230102062417740

image-20230102062426531

本章小结

  • 对于面向对象的软件系统涉及来说,在支持可维护性的同事,需要提高系统的可复用性
  • 软件的服用可以提高软件爱你的开发效率,提高软件质量,节约开发成本,恰当地复用还可以改善系统的可维护性
  • 单一职责原则要求在软件系统中,一个雷只负责一个功能领域的相应职责
  • 开闭原则要求一个软件实体应当对扩展开放对修改关闭,即在不修改源代码的基础上扩展一个系统的行为
  • 里氏代换原则可以通俗表述为在软件中如果能够使用几基类对象那么一定能够使用其子类对象
  • 依赖倒转原则要求抽象不应该依赖于细节,细节应该依赖于抽象;要针对接口编程不要针对实现编程
  • 接口隔离原则要求客户端不应该依赖于那些他不需要的接口,即将一些大的接口细化成一些小的接口供客户端使用
  • 合成复用原则要求复用时尽量使用对象组和,而不使用集成。
  • 迪米特法则要求一个软件实体应当尽量少的与其他实体发生相互作用。

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

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

相关文章

Educational Codeforces Round 92 (Rated for Div. 2) B. Array Walk

翻译: 给定一个数组𝑎1,𝑎2,…,𝑎𝑛,由𝑛个正整数组成。 最初,您位于索引1,分数等于𝑎1。你可以执行两种动作: 向右移动…

CDN

CDN——Content Delivery Network,内容分发网络。 具体来说,CDN就是采用更多的缓存服务器(CDN边缘节点),布放在用户访问相对集中的地区或网络中。当用户访问网站时,利用全局负载技术,将用户的访…

【CSP】邻域均值

邻域均值 邻域均值 题意比较好理解,就是算一些数字。如果采用暴力方法的话,就是用一个边长为 2∗r12*r12∗r1 的正方形框框住大矩阵,然后遍历这个框,求出其平均值,然后移动正方形框,直到大矩阵内所有像…

【免费开放源码】审批类小程序项目实战(预约审批端)

第一节:什么构成了微信小程序、创建一个自己的小程序 第二节:微信开发者工具使用教程 第三节:深入了解并掌握小程序核心组件 第四节:初始化云函数和数据库 第五节:云数据库的增删改查 第六节:项目大纲以及制…

6.5 特殊用途语言特性

文章目录默认实参使用默认实参调用函数默认实参声明默认实参初始值内联函数和constexpr函数内联函数constexpr 函数把内联函数和constexpr函数声明在头文件内调试帮助assert预处理宏NDEBUG预处理变量默认实参 某些函数有这样一种形参,在函数的很多次调用中它们都被赋予一个相同…

电子游戏销售之缺失值检测与处理

电子游戏销售之缺失值检测与处理 文章目录电子游戏销售之缺失值检测与处理0、写在前面1、数据缺失值预处理1.1 表的形状1.2 原始数据每个特征缺失和非缺失的数目1.3 每个特征缺失的率1.4 处理后各特征缺失值的数目1.5 删除缺失值后的数据展示2、替换法处理缺失值2.1 替换法2.2 …

1.Springboot配置细节

一、参考资料 13-SpringBoot配置-项目外部配置加载顺序_哔哩哔哩_bilibili 二、配置 2.1 配置文件 注意变量后面是:,而不是等号 2.2 读取配置文件 2.2.1 Value 比如配置文件application.properities中定义了一个name,其值为abc。 代码里面只需按照如…

一、软件安装与配置

一、PyTorch环境软件安装与配置 1.安装anaconda参考 anaconda老版本下载方法(如何查看anaconda与python版本对应关系)及安装教程_breadth_的博客-CSDN博客_anaconda旧版本下载 2.在anconda下安装和激活pytorch环境 此步并没有下载pytorch 3.下载pyto…

云计算运营—03 KVM虚拟化技术方案介绍

KVM虚拟化技术方案介绍 1.背景介绍 KVM(Kernel-based Virtual Machine) 开源全虚拟化方案 支持体系结构 x86(32位,64位)、IA64、PowerPC、S390 依赖x86硬件支持:Intel VT-x/ AMD-V内核模块,使得linux内核成为hypervisor XEN架构 …

《B-树》

tips:B-树读成b树,并不是b减树 【一】基本搜索结构 种类数据格式时间复杂度顺序查找无要求O(N)二分查找有序O(log2N)二叉搜索树无要求O(N)二叉平衡树(AVL和红黑树)无要求,最后随机O(log2N)哈希无要求O(1)位图无要求O…

linux系统中SPI驱动框架的基本原理与实现

大家好,今天主要和大家聊一聊,如何使用linux系统中SPI驱动ICM-20608六轴传感器的操作。 目录 第一:linux系统下SPI驱动框架简介 第二:SPI设备驱动编写 第三:SPI设备和驱动匹配过程 第一:linux系统下SPI驱…

MySQL数据库高级面试题(1)

✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:Java面试题…

CSDN年度征文 | 你好,2023

祝大家新年快乐~🧧🧧🧧⭐过去的2022⭐2022已成过去,2023慢步向我们走来。回首2022,这一年不是平凡的一年。这一年,有苦也有乐。冬奥会的成功举办、香港回归25周年、二十大胜利召开、航天任务圆满成功等等都…

设计 | 分享5个好用的PPT模板网站

第一PPT 这个老牌的模板网站了,全站都是免费下载,还是不错的 但是素材质量嘛,免费所以不太高。 第一PPT下载https://www.1ppt.com/ 模板狗 这个是最近发现的一个网站,其中内容比较精美。 而且不用开会员也能单独购买&#x…

【Android】APT

引言: 安卓中APT又叫Annotation Processing Tool,即注解处理器。Java中注解分为编译时注解和运行时注解,编译时注解无法通过反射的方式进行获取和处理,所以我们可以利用APT处理编译时注解。比如常见的三方库ButterKnife、ARouter…

mysql删除重复记录并且只保留一条

准备的测试表结构及数据 插入的数据中A,B,E存在重复数据,C没有重复记录 CREATE TABLE tab ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(20) DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT13 DEFAULT CHARSETutf8; -- --------------------…

使用root用户和普通用户完成分配任务案例 ansible(1)

目录 案例一: 控制主机和受控主机通过root用户通过免密验证方式远程控制受控主机实施对应任务。 案例二: 控制主机连接受控主机通过普通用户以免密验证远程控制受控主机实施特权指定操作。 案例一: 控制主机和受控主机通过root用户通过免…

<网络概述>——《计算机网络》

目录 1.网络基础 1.1 计算机网络背景 1.2 网络发展 1.3 软件分层 1.4 网络和操作系统的关系 1.5 局域网通信的原理 2. 网络协议 2.1 网络协议初识 2.1.1 协议分层 2.2 OSI七层模型 2.3 TCP/IP五层(或四层)模型 3. 网络传输基本流程 3.1 网络传输流程图 3.2 数据包…

密码技术扫盲,Part 3:认证

个人博客 密码技术扫盲,Part 1:对称加密密码技术扫盲,Part 2:非对称加密🎯 密码技术扫盲,Part 3:认证 除了加密,还有一类用法是对信息的认证,主要包括 4 个技术 单向散…

PostgreSQL JIT 实现query性能加速的一些补充

文章目录背景Executor 本身做的一些优化LLVM JIT 的优化本地以及全局优化执行 query 时的优化JIT调度优化 过程背景 之前介绍过一次 PostgreSQL JIT with LLVM 实现,因为有一些细节没有介绍得很清楚,需要额外做一些补充。 关于LLVM 的IR 以及 如何 用LL…