设计模式——需要遵循的七个设计原则

1 概述

面向对象编程有七大原则,设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

2 七个设计原则
2.1 单一职责原则(SRP)
Single Responsibility Principle,定义是一个类,应该只有一个引起它变化的原因。

类变化的原因就是职责,如果一个类承担的职责过多,就等于把这些职责耦合在一起了。在设计类的时候,应该要让每一个类仅有一个职责,每一个类只做一类事情,这就是单一职责原则。

一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。而如果想要避免这种现象的发生,就要尽可能的遵守单一职责原则。此原则的核心就是解耦和增强内聚性。

2.2 开闭原则 ( OCP )
Open Close Principle,定义是软件实体(包括类、模块、函数等)应该对于扩展时开放的,对于修改是封闭的。

“开放”就是指开放接口,也就是通过增加子类的方法来增加功能;“封闭”指的是封闭修改,也就是代码一旦提交,就不要再去修改它。

但是,在实际开发中,“封闭”是相对的,不能保证类写完后永远不需要修改。因此,在设计类的时候,需要考虑类的扩展,然后把这些扩展抽象出一个公共父类,父类中有子类都会执行的函数;这样,增加新功能时只要新建一个类,继承父类,覆盖父类中的函数,然后客户端需要使用新功能时,只要将新的子类对象赋给父类引用,再通过父类引用调用函数即可。

在设计或开发类的时候如果没有将未来可能扩展的功能考虑到,一旦发现需要扩展功能并且需要修改原来代码,就立刻给这个类抽象出父类,让原本的功能和新增的功能都继承这个父类。

开闭原则是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。

2.3 里氏替换原则 ( LSP )
Liskov Substitution Principle,是面向对象设计的基本原则之一。 定义是任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏替换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。

2.4 依赖倒置原则 ( DIP )
Dependence Inversion Principle,这个原则是开闭原则的基础,依赖倒置原则就是要求调用者和被调用者都依赖抽象,这样两者没有直接的关联和接触,在变动的时候,一方的变动不会影响另一方的变动。

调用模块中引用类型的变量不应该指向某一个具体的实现类,而应该指向一个抽象类或接口;被调用模块应该是一个接口/抽象类的实现类/子类。依赖倒置强调了抽象的重要性,针对接口编程,依赖于抽象而不依赖于具体。

面向实现编程的弊处:

如果是面向实现编程,即高层模块调用低层实现函数,那么当高层模块想要换一种实现的时候,就需要修改高层模块的代码,让它调用另外一个实现函数。由于修改了客户端的代码,所以破坏了“封闭修改”的原则。

面向接口编程的好处:

若高层模块一开始调用的是接口中的抽象函数,那么当高层类需要换一个函数实现的时候,高层类就不需要修改任何代码,在低层模块中创建一个实现接口的类,并重写接口中的函数,然后在高层类/低层类中创建实现类的对象并赋给抽象接口的引用即可,最好的做法是在配置文件中换。

 

(图片来源:https://blog.csdn.net/u010425776/article/details/48132861)

(1)高层类中换实现

当低层类创建完一个新的实现类之后,在高层类中需要调用实现类函数的地方作如下修改:

接口 接口对象 = new 旧的实现类();——>接口 接口对象 = new 新的实现类();

这种方式在客户端仍然需要修改。

(2)在低层类中换实现

低层类中需要再创建一个工厂,接口引用究竟指向哪个实现类的对象就由工厂类决定:

class Factory(){
接口  getBean(){
return new  旧的实现类();

}

}

class Factory(){
接口  getBean(){
return new  新的实现类();

}

}

(3)在配置文件中更换实现

Spring采用了一种更加科学的方式,在配置文件中配置接口对应的实现类是哪一个。这样在程序运行的过程中,首先会读取配置文件,将用户指定的那个实现类的对象赋给接口引用。

如果用户想修改一种实现,只需在配置文件中换一下即可。

2.5 接口隔离原则 ( ISP )
Interface Segregation Principle,这个原则的意思是使用多个隔离的接口,比使用单个接口要好。目的就是降低类之间的耦合度,便于软件升级和维护。

2.6 最少知道原则(迪米特原则)
如果两个类不必彼此间直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则的初衷在于降低类之间的耦合。因为一个类的藕合程度越弱,那么当这个类内部发生修改时,就不会波及到该类的使用者们。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

降低藕合的方法:

尽量使一个类中能私有的成员私有化,只给外界提供简单的接口即可。

高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则;低耦合是指在一个完整系统,模块之间尽可能相互独立,模块与模块之间的接口,尽量的少而简单。

2.7 合成/聚合复用(CARP)
Composite Reuse Principle,合成/聚合复用原则经常又叫做合成复用原则,是开闭原则的具体实现规范。合成/聚合复用原则的潜台词是:我只是用你的方法,我们不一定是同类。继承的耦合性更大,比如一个父类后来添加实现一个接口或者去掉一个接口,那子类可能会遭到毁灭性的编译错误,但如果只是组合聚合,只是引用类的方法,就不会有这种巨大的风险,同时也实现了复用。

实现方法:

通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。

posted @ 2021-04-23 16:10  独自一人的江湖  阅读(167)  评论(0)    收藏  举报