设计原则是架构的灵魂,设计模式是具体的实现
单一职责原则
定义
单一职责原则(SRP:Single responsibility principle)又称单一功能原则。它规定一个类应该只有一个发生变化的原因
特点
- 降低类的复杂性,对类或接口的职责有清晰明确定义
- 提高可读性
- 提高可维护性
- 降低变更引起的风险,接口改变只影响相应的实现类,不影响其他类
重点
- 接口一定要做到单一职责
- 类的单一职责比较难以实现,尽量做到只有一个原因引起变化
- 一个方法尽可能做一件事,能分解就分解,分解到原子级别
适用范围
接口,类,方法
里氏替换原则
定义
所有引用基类的地方必须能透明地使用其子类的对象
也就是说用子类替换父类,也不会产生问题
优缺点
继承角度
- 优点
代码共享:共享代码,子类都拥有父类的方法和属性,将父类的代码共享给了子类
重用性:提高代码的重用性,子类重用父类的代码
子父类异同:子类形似父类,异于父类,父子都不同
扩展性:提高代码的可扩展性,子类就可以为所欲为了,子类可以随意扩展父类
开放性:提高产品或项目的开放性,父类随意扩展,开放性随之增加了 - 缺点
侵入性:继承是侵入性的,子类强制继承父类的方法和属性
灵活性:降低代码的灵活性,子类必须拥有父类的属性和方法,子类收到了父类的约束,这是从子类的角度讲得
耦合性:增强了耦合性,父类的属性和方法被修改时,还需要顾及其子类,可能会带来大量的重构,这是从父类的角度讲的
非继承角度的缺点
将子类单独作为一个业务来使用,会让代码间的耦合关系都复杂,缺乏类替换标准
将子类当做父类用,抹杀了子类的个性
重点
返回值:父类方法返回值类型F,子类方法返回值类型S,里氏替换原则是S范围必须小于F
重载:父类子类方法参数类型或者数量不同,如果要符合里氏替换要求的话,子类参数必须>=父类参数,即不能让子类自己定义的方法被调用
注意事项
如果想要使用里氏替换,尽量避免让子类拥有自己单独的成员变量或者方法,如果子类个性多了,子类父类关系很难调和
依赖倒置原则
定义
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象
问题引申
类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险
将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率
好处
- 减少类之间的耦合
- 提高系统稳定性
- 降低并发风险
- 提高代码可读性
依赖倒置注入实现
- 构造函数依赖对象:注入方法:通过构造函数参数声明依赖对象,即构造函数注入
- Setter方法依赖对象:通过Setter函数参数声明依赖对象,即构造函数注入
- 接口注入依赖对象:在接口方法的参数中声明依赖对象,即接口注入
依赖倒置本质
通过抽象即接口或者抽象类,使各个类和模块实现彼此独立,实现模块间松耦合
注意点
尽量不要覆盖方法,如果方法在抽象类中已经实现,子类不要覆盖
使用场景
- 依赖倒置在小项目中得有点很难体现出来,是否采用依赖倒置原则影响不大
- 项目越大,需求改变越多,采用依赖倒置原则设计的接口或抽象类对实现类的约束,会大大减少维护成本
接口隔离原则
定义
接口隔离定义:建立单一的接口,功能尽量细化,不要建立臃肿的接口
- 不需要的接口:客户端尽量不依赖其不需要的接口,客户端需要什么接口就提供什么接口,剔除不需要的接口,对接口进行细化,保持接口方法最少
- 最小接口:类间的依赖关系应该建立在最小接口上,细化接口
单一职责与接口隔离区别
单一职责:注重职责,注重业务逻辑上得划分
接口隔离:注重的是接口的方法尽量少
特点
- 接口尽量小
拆分接口:接口隔离的核心定义,不出现臃肿的接口
拆分时注意点:
限制:接口小有限度,不能违反单一职责原则,不要将一个业务逻辑拆分成两个接口
要求:根据接口隔离原则拆分接口时,必须满足单一职责原则 - 接口高内聚
高内聚:提高接口,类,模块的处理能力,减少对外界交互
具体方法:接口中尽量少公布public方法,对外公布的public方法越少,变更的风险就越小,有利于后期的维护 - 定制服务
起源:系统模块间的耦合需要有相互访问的接口,这里就需要为各个客户端的访问提供定制的服务接口
要求:只提供访问者需要的方法,不需要的就不提供 - 接口隔离限度
粒度小:接口粒度越小,系统越灵活,但是同时使系统结构复杂,开发难度增加,降低了系统的可维护性
粒度大:灵活性降低,无法提供定制服务,增大项目风险 - 原子接口划分原则
接口模块对应关系:一个接口只服务于一个子模块或业务逻辑
方法压缩:通过业务逻辑,压缩接口中得public方法,减少接口的方法的数量
修改适配:尽量去修改已经污染的接口,如果变更风险较大,采用适配器模式进行转化处理
迪米特法则
定义
最少知识原则,一个对象应该对其它对象有最少的了解,即一个类对自己需要耦合或者调用的类知道的最少
优缺点
优点:类间解耦,弱耦合,耦合降低,复用率提高
缺点:类间的耦合性太低,会产生大量的中转或跳转类,会导致系统的复杂性提高,加大维护难度
开闭原则
定义
软件的实体类,模块,函数应该对扩展开放,对修改关闭;即软件实体应该通过扩展实现变化,不是通过修改已有的代码实现变化
优点
利于测试:如果改变软件内容,需要将所有的测试流程都执行一遍,如单元测试,功能测试,集成测试等,如果只是扩展,只单独测试扩展部分即可
提高复用性:所有逻辑都从原子逻辑组合,原子逻辑粒度越小,复用性越大;这样避免相同逻辑存在,修改时需要修改多个此相同逻辑
提高可维护性:维护一个类最好的方式是扩展一个类,而不是修改一个类,如果需要修改需要读懂源码才能修改,扩展的话只需要了解即可,直接继承扩展