面向对象的七大原则



总脉络图:

一:单一职责原则(全称:“Single-Responsibility Principle”)又称 单一功能原则


 

核心:解耦和增强内聚性(高内聚,低耦合)

说明:

就一个类而言,应该只专注于做一件事和仅有一个引起它变化的原因。所谓职责,我们可以理解他为功能,就是设计的这个类功能应该只有一个,而不是两个或更多。也可以理解为引用变化的原因,当你发现有两个变化会要求我们修改这个类,那么你就要考虑撤分这个类了。因为职责是变化的一个轴线,当需求变化时,该变化会反映类的职责的变化。

使用SRP注意点

1、一个合理的类,应该仅有一个引起它变化的原因,即单一职责;

2、在没有变化征兆的情况下应用SRP或其他原则是不明智的;

3、在需求实际发生变化时就应该应用SRP等原则来重构代码;

4、使用测试驱动开发会迫使我们在设计出现臭味之前分离不合理代码;

5、如果测试不能迫使职责分离,僵化性和脆弱性的臭味会变得很强烈,那就应该用Facade或Proxy模式对代码重构;SRP优点:消除耦合,减小因需求变化引起代码僵化。

 

二、依赖倒转原则(全称:“Dependence Inversion Principle”)又称 依赖倒置原则或依赖反转原则


 

核心:要依赖于抽象,不要依赖于具体的实现

优点:使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

怎样做到依赖倒置?

以抽象方式耦合是依赖倒转原则的关键。抽象耦合关系总要涉及具体类从抽象类继承,并且需要保证在任何引用到基类的地方都可以改换成其子类,因此,里氏代换原则是依赖倒转原则的基础。

在抽象层次上的耦合虽然有灵活性,但也带来了额外的复杂性,如果一个具体类发生变化的可能性非常小,那么抽象耦合能发挥的好处便十分有限,这时可以用具体耦合反而会更好。

层次化:所有结构良好的面向对象构架都具有清晰的层次定义,每个层次通过一个定义良好的、受控的接口向外提供一组内聚的服务。

依赖于抽象:

建议不依赖于具体类,即程序中所有的依赖关系都应该终止于抽象类或者接口。

尽量做到:

1、任何变量都不应该持有一个指向具体类的指针或者引用。

2、任何类都不应该从具体类派生。

3、任何方法都不应该覆写它的任何基类中的已经实现的方法。

 

三:接口隔离原则(全称:“Interface Segregation Principle”)


 

核心思想:

不应该强迫客户程序依赖他们不需要使用的方法。

 

接口分离原则的意思就是:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口当中.

 

分离接口的两种实现方法:

 

1.使用委托分离接口。(Separation through Delegation)

 

2.使用多重继承分离接口。(Separation through Multiple Inheritance)

 

四:迪米特原则(全称:“Law of Demeter”) 又称 最少知识原则


 

说明:

对象与对象之间应该使用尽可能少的方法来关联,避免千丝万缕的关系。

如何实现迪米特法则?

迪米特法则的主要用意是控制信息的过载,在将其运用到系统设计中应注意以下几点:

1) 在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。

2) 在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。

3) 在类的设计上,只要有可能,一个类应当设计成不变类。

4) 在对其它对象的引用上,一个类对其它对象的引用应该降到最低。

 

五:开闭原则(全称:“Open-Closed Principle”)


 

核心思想:对扩展开放,对修改关闭。

 

优点:

按照OCP原则设计出来的系统,降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,这样就无须为原有模块进行重新测试。

 

如何实现“开-闭”原则?

 

在面向对象设计中,不允许更改的是系统的抽象层,而允许扩展的是系统的实现层。换言之,定义一个一劳永逸的抽象设计层,允许尽可能多的行为在实现层被实现。

 

解决问题关键在于抽象化,抽象化是面向对象设计的第一个核心本质。

 

对一个事物抽象化,实质上是在概括归纳总结它的本质。抽象让我们抓住最最重要的东西,从更高一层去思考。这降低了思考的复杂度,我们不用同时考虑那么多的东西。换言之,我们封装了事物的本质,看不到任何细节。

 

在面向对象编程中,通过抽象类及接口,规定了具体类的特征作为抽象层,相对稳定,不需更改,从而满足“对修改关闭”;而从抽象类导出的具体类可以改变系统的行为,从而满足“对扩展开放”。

 

对实体进行扩展时,不必改动软件的源代码或者二进制代码。关键在于抽象。

 

六:合成复用原则(全称:Composite Reuse Principle,CRP)


核心思想:

 

尽量使用对象组合,而不是继承来达到复用的目的。该原则就是在一个新的对象里面使用一些已有的对象,

 

使之成为新对象的一部分:新的对象通过向这些对象的委派达到复用已有功能的目的。

 

复用的种类:

 

1.继承

 

2.合成聚合

 

注:在复用时应优先考虑使用合成聚合而不是继承

只有当以下的条件全部被满足时,才应当使用继承关系。

         1. 子类是超类的一个特殊种类,而不是超类的一个角色,也就是区分“Has-A”和“Is-A”.只有“Is-A”关系才符合继承关系,“Has-A”关系应当使用聚合来描述。

         2 .永远不会出现需要将子类换成另外一个类的子类的情况。如果不能肯定将来是否会变成另外一个子类的话,就不要使用继承。

         3 .子类具有扩展超类的责任,而不是具有置换掉或注销掉超类的责任。如果一个子类需要大量的置换掉超类的行为,那么这个类就不应该是这个超类的子类。

         错误的使用继承而不是合成/聚合的一个常见原因是错误地把“Has-A”当成了“Is-A”.”Is-A”代表一个类是另外一个类的一种;而“Has-A”代表一个类是另外一个类的一个角色,而不是另外一个类的特殊种类。

 

七:里氏替换原则(全称:“Liskov Substitution Principle”)


 

核心:

1.在任何父类出现的地方都可以用他的子类来替代(子类应当可以替换父类并出现在父类能够出现的任何地方)

子类必须完全实现父类的方法。在类中调用其他类是务必要使用父类或接

口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。

2.子类可以有自己的个性。子类当然可以有自己的行为和外观了,也就是方法和属性

3.覆盖或实现父类的方法时输入参数可以被放大。即子类可以重载父类的方法,但输入参数应比父类方法中的大,这样在子类代替父类的时候,调用的仍然是父类的方法。即以子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松。

4.覆盖或实现父类的方法时输出结果可以被缩小。

 

 

 

转载于:https://www.cnblogs.com/hq-123/p/5383069.html

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

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

相关文章

福建工程学院寒假作业G题

涨姿势题就是所谓的优化题,在组队赛中,队伍发现了一题水题,那么应该交给谁去处理?作为处理水题的代码手,应该具备什么样的素养?1,要快,水题拼的就是速度!2,不…

excel 多列匹配相等后 引用值

2019独角兽企业重金招聘Python工程师标准>>> 场景 如图下,当A、B列与E、F列皮配上,C列则引用G列的值 原理 VLOOKUP只能查找单列值。我们可以把多列值拼接后形成一个虚拟列,然后VLOOKUP函数查找这个虚拟列进行匹配。 在C1处输入下…

【BUG调试】——OSError: Caught OSError in DataLoader worker process 0

目录 问题描述: 参考链接 问题分析 解决方案 出现情况 问题描述: 在使用pytorch搭建了VGG从头开始训练时出现了以下问题: OSError: Caught OSError in DataLoader worker process 0 参考链接 参考up主视频:4.2 使用pytor…

cvAdd()和 cvAddS()函数的使用

函数原型如下: voidcvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* maskNULL ); src1 第一个原数组 src2 第二个原数组 dst 输出数组 mask 操作的复盖面, 8-bit单通道数组; 只有复盖面指定的输出数组被修改。 函数 cvAdd 加一个数…

设计模式之接口隔离原则

这个原则想必大家从字面就可以猜出大体的含义,其实这个原则可以说是依赖倒置原则的一种进化补充,因为依赖倒置原则告诉我们实现类的各种依赖关系应该尽量隔离在抽象里面,同时底层的接口协议不应该依赖上层协议的变更而变更,所以我…

iOS 图解多线程

转载于:https://www.cnblogs.com/OnNineMonkey/p/5385963.html

Egret之位图字体

1 , 关于位图字体的制作 2 , egret官方提供的资源 看看cartoon-font.fnt的内容 {"file":"cartoon-font.png","frames":{ "A":{"x":1,"y":54,"w":21,"h":24,"offX":2,"offY&qu…

【机器视觉】——平面测量实际尺寸(像素尺寸转物理尺寸)

目录 方法一:比例尺法 方法:二:三角法 方法三:相机标定 以下方法均在平面的前提下进行 方法一:比例尺法 在一张纸上绘制一个带刻度的直线,将纸张放在摄像头下,抓取任意两点的像素坐标,计算像素距离pd,再根据刻度读取实际距离ad,根据两者可以求出缩放比例,即地图上…

图像处理基本算法-滤波

线性滤波器的向量表示: W是一个大小为m*n的滤波器的系数,Z为由滤波器覆盖的相应图像的灰度值。 线性滤波器所能是实现的就是乘积求和操作。 几种常见的滤波器: 平滑空间滤波器如均值滤波 统计排序滤波器如中值滤波 锐化空间滤波器如锐化…

20145122《Java面向对象程序设计》实验二实验报告

实验名称: Java面向对象程序设计 实验内容: 初步掌握单元测试和TDD理解并掌握面向对象三要素:封装、继承、多态初步掌握UML建模熟悉S.O.L.I.D原则了解设计模式 PSP时间 步骤耗时百分比需求分析1h12.5%设计1h12.5%代码实现3h37.5%测试1h12.5%分…

iOS中AutoLayer自动布局流程及相关方法

关于UIView的Layer,IOS提供了三个方法: 1、layoutSubviews 系统重写布局:在iOS5.1和之前的版本,此方法的缺省实现不会做任何事情(实现为空),iOS5.1之后(iOS6开始)的版本,此方法的缺省实现是使用你设置在此view上面的co…

移动开发web第一天

一、适配问题解决方案:流式布局 viewport1、流式布局百分比布局,通过设置盒子的宽度为百分比来根据屏幕的大小进行伸缩,特点是不受固定像素的限制,内容向两侧填充2、viewport在移动端用来承载网页的这个区域,就是我们…

均值滤波 中值滤波 高斯平滑滤波

均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素…

javaWeb开发总结 ---- 前端数据插入到后台

一,概述: 本文主要描述如何将数据通过表单提交到后台并插入到数据库.其中后台使用spring框架. 二,开发流程: 明确需求,即将什么数据插入到数据库平台搭建,配置spring, 数据库&#…

对clear float 的理解

之前自己对于清除浮动的用法比较模糊 ,如果用到的话,一般都是采用简单粗暴的方式解决,就是直接用overflow:hidden,但是越用久就会发现其实有BUG,这个BUG正是overflow:hidden带来的,因…

【机器视觉】——相机标定降低重投影误差方法

目录 一、标定结果分析 二、影响标定误差的原因 1、平面标定板黑白棋盘格的精度

linux 安装RedisLive

为什么80%的码农都做不了架构师?>>> RedisLive 用来监控Redis,便于redis性能分析 安装步骤: 1.安装pip(代码参考:https://github.com/pypa/pip) 官方网站:https://pypi.python.org/…

高斯滤波和双向滤波的区别与联系

1. 简介 图像平滑是一个重要的操作,而且有多种成熟的算法。这里主要简单介绍一下Bilateral方法(双边滤波),这主要是由于前段时间做了SSAO,需要用bilateral blur 算法进行降噪。Bilateral blur相对于传统的高斯blur来说…

Eclipse变量名自动补全问题 自定义上屏按键为TAB

Eclipse空格等号等都可以上屏,这样有时候输入变量名再按空格就会自动补全,非常讨厌。那么怎么办呢? 1.首先你的Eclipse需要装有 Eclipse plug-in development environment 和 Eclipse JDT Plug-in Developer Resources 或者直接去下载一个和…