设计原则
# 设计原则
# 开闭原则(Open Closed Principle,OCP)
定义
软件实体应该对功能的拓展开放,对修改关闭的原则, 因为需求有变化,要求我们设计程序时必须为程序功能的新增留好接口,在新增功能时,不要修改原有代码,而是新增代码.让程序实现对拓展开放,对修改关闭测设计要求
举例
MVC模式下,每一层都有接口,是和其他层对接的规范,新增功能时,我们可以选择新增Controller层和service层和mapper层代码 不用去修改原有代码
# 里氏替换原则(Liskov Substitution Principle,LSP)
定义
所有引用的基类的地方必须能够透明的使用其子类的对象
凡是父类出现的地方,其子类就可以出现,而且调用子类还不能产生多于父类的错误和异常,调用者根本就不要需要知道是子类还是父类对象.但是反过来就不行,子类出现的地方父类未必就能使用
1子类必须完全实现了父类的方法,具备父类完全的功能
2子类可以有自己的特征
3覆盖和实现父类方法时,输入的参数可以被放大,但是不能被缩小
4覆盖和实现父类方法时,输出的结果可以被缩小,但是不能被放大
5覆盖和实现父类方法时,产生的异常可以被缩小,但是不能被放大
举例
白马 马也
乘白马 乘马也
黑马 马也
乘黑马 乘马也
乘的是马 什么颜色的马都是马
马 是父类 各种颜色的马是子类 要求的是父类,所有的子类对象都可以使用
# 依赖倒置原则(Dependence Inversion Principle,DIP)
定义
高层模块不应该依赖底层模块,两者都应该依赖抽象,抽象不应该依赖细节,细节应该依赖抽象
抽象:即是抽象类或者接口,两者是不能够实例化的
细节:即是具体的嫌累,实现接口或者继承抽象类的类
依赖正置就是类之间的依赖是实实在在的实现类之间的依赖,也就是面向实现编程
依赖倒置就是通过抽象(抽象类或者接口),使各个模块之间实现彼此独立,不相互应影响
举例
一个类组合另一个类作为属性时,应尽量选择抽象类或者是接口,尽量避免直接组合实现类
电脑里的零件坏了,如硬盘,内存,CPU等,那么直接更换对应的配件,只要插槽一样就能互换,维护比较方便.插槽就是接口,具体的硬件就是实现类.留好接口可以随时换零件,如果零件直接焊死在电脑上,坏了就没有办法更换了
# 单一职责原则(Single Responsibility Principle,SRP)
定义
应该有且仅有一个原因引起类的变更
1系统中的每个类都应该只有一个职责,而所有类所关注的就是自身之职责的完成
2职责是指为”变化的原因”
3如果能想到多个原因去改变一个类,这个类就是多个职责
4并不是单一功能原则,并不是每个类只能有一个方法,而是单一”变化的愿意”原则
5如果一个类有多个职责,这些职责就耦合在了一起,当一个职责发生变化时,可能会影响其他职责
6多个职责耦合在一起,会影响服用性(可能只需要服用该类的某一个功能,但是该职责和其他职责耦合在一起,很难分离出来)
其实就是我们常说的高内聚低耦合原则,.单一职责原则是最简单也非常难实现的原则
举例
公司老板 既当销售,又当技术,又当运维,又当售后。这不合适
# 接口隔离原则(Interface Segregation Principle,ISP)
定义
客户端不应该强行依赖他不需要的接口,类之间的依赖关系应该建立在最小的接口上,建立单一接口,不要建立庞大臃肿的接口,应该尽量细化接口,接种的方法尽量少,也就是说要为各个类建立专门的接口,而不要试图去建立一个庞大的接口供所有的依赖它的类去调用
接口隔离原则使用的一些规范
1接口尽量小,尽量细致
2接口尽量高内聚,尽量和其他接口撇清关系
3定制服务,为调用者提供且之提供他需要的方法
4接口设计有限度,根据业务及经验,仔细四高筹划,适度隔离接口
单一职责和接口隔离辨析
1单一职责原则侧重职责,接口隔离侧重对接口的依赖的隔离
2单一职责原则侧重约束类,其次是接口,针对程序中实现的细节
3接口隔离原则侧重约束接口,主要针对抽象需求,针对程序的整体框架的构建
举例
微服务的业务划分,约定同类业务抽象出公共接口
# 迪米特法则(Law of Demeter,LoD)
定义
只与你只直接的朋友通信 ,不要和不相关的人产生大量通信,如果两个类不必彼此通信,那么两个类就不应到发生直接的相互作用,如果其中的一个类需要调用另一个类的方法的话,可以通过第三者转发这个调用
迪米特法则的初衷是在于降低类之间的耦合.但是迪米特法则有可能造成一个后果就是程序中存在大量的中介类,这些中介类完全就是为了传递类间的相互调用关系,一定程度上增加了系统的复杂度
举例
找中介卖房子,不用我们自己直接接触大量的买房人员
# 合成复用原则(Composite Reuse Principle,CRP)
定义
当一个类想使用另一个类的功能时,优先使用对象的组合,而不是继承,尽量多使用组合
合成聚合复用原则是值在一个新对象中通过组合关系使用原来已有的一些对象,使之成为新对象的一部分,通过使用已有对象的API完成已有功能的调用
为什么要是用合成聚合,尽量不要使用继承?
1继承破坏包装,把超类的实现细节直接暴露给子类,不利于信息的隐匿
2如果父类发生改变,会引发一系列子类的改变,类之间耦合度高
3继承是一种静态功能的使用,在运行的过程中不能发生改变,聚合复用可以动态传入子类对象实现功能动态改变
举例
汽车上如果想获得行车记录的功能,单独组合一个行车记录仪对象作为属性即可,没有必要继承行车记录仪类