面向对象的七大原则



总脉络图:

一:单一职责原则(全称:“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,一经查实,立即删除!

相关文章

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…

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…

图像处理基本算法-滤波

线性滤波器的向量表示: 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…

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

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

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 或者直接去下载一个和…

Dreamweaver CS6 Mac破解版

介于之前小子分享的Mac版的Adobe的PS CS6和Illustrator CS6,有用户要求小子分享下Dreamweaver,小子当然乐意效劳。 Dreamweaver CS6 是世界顶级软件厂商Adobe推出的一套拥有可视化编辑界面,用于制作并编辑网站和移动应用程序的网页设计软件。…

【pyqt5学习】——graphicView显示matplotlib图像

目录 一、导入模块 二、自定义一个matplotlib窗口类Figure 三、利用QT_designer绘制窗口 四、写逻辑代码 五、结果展示 一、导入模块 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplo…

what is ssao

说到ssao 就要从ao说起,ao,即间接环境光遮蔽技术。我们知道现实中的光线,除了来自太阳和电灯的直射光线以外,光线碰到物体以后,还会再次反射,折射,而再次反射折射的过程中,又会被其他…

【pyqt5学习】——groupBox显示matplotlib图像

目录 一、导入模块 二、创建matplotlib窗口类 三、qt_designer设计窗口 四、逻辑代码 五、结果展示 一、导入模块 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure impor…

杭电1027Ignatius and the Princess II模拟

地址:http://acm.hdu.edu.cn/showproblem.php?pid1027 题目: Problem DescriptionNow our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about to kill our pretty Princess. But now the BEelzebub has t…

angular 使用rxjs 监听同级兄弟组件数据变化

angular 的官网给出了父子组件之间数据交互的方法,如ViewChild、EventEmitter 但是如果要在同级组件之间进行数据同步,似乎并没有给出太多的信息。 有时候我们想,在一个组件中修改数据之后,马上反映到另外一个组件中, …

pic

转载于:https://www.cnblogs.com/edisonxiang/p/5392651.html

OpenCV之cvSmooth函数平滑滤波

1、cvSmooth函数用法 定义原型 <span style"font-size:12px;"> void cvSmooth( const CvArr* src, CvArr* dst,int smoothtypeCV_GAUSSIAN,int param1, int param2, double param3, double param4 );</span>src:输入图像. dst:输出图像. smoot…

【python数字信号处理】——DFT、DTFT(频谱图、幅度图、相位图)

目录 一、离散时间傅里叶变换DTFT 二、离散傅里叶变换DFT 三、DFT与DTFT的关系 ​ 参考&#xff1a; 《数字信号处理》——&#xff08;一&#xff09;.DTFT、DFT(python实现)_远行者223的博客-CSDN博客python绘制频谱图DTFT&#xff0c;DFTpython绘制频谱图&#xff1a;…