Single responsibility principle 单一职责原则
原理
一个类应该仅仅只有一个被修改的理由,也就是一个类只有一个职责;而不是一种功能。
缺点
- 因为不同原因修改类的时候,也可能因为不相关的修改导致功能间的相互影响。
- 单个类承担的职责越多,意味着类的复杂度也就越高,维护成功也就越高。
如何解决
- 拆分大类为多个小类
- 将一些功能抽取为公共的函数
Open-closed principle 开放-关闭原则
原理
类应该对扩展开放,对修改封闭;应该可以在不修改某个类的前提下,扩展它的行为。
改造方法
使用类继承来改造代码
找到你类中会变动的部分,将其抽象成新的方法或者属性,最终允许新的子类来重写它以改变类似的行为。
使用组合与信赖注入来改造代码
将需要变化的内容,抽象为类,并将不同的原则实现不同的类,在调用主类进行操作的时间,不同的继承结果会让类有不同的变化,但是这种方案,并不会修改主类,因为接受的类型为变化的类的祖先,也就是保证的类的不变,但是传入的内容变化却是变的。
使用数据驱动思想来改造代码
数据驱动也就是将经常变化的东西完全以数据的方式抽离出来,当需求变动时,只改动数据,代码逻辑保持不变。
三种方案的区别
类继承与依赖注入方式的区别
两个原则都运用了继承来优化代码,第一个方案重点在于扩展类的行为,但是又保证父类的行为不变;第二种方案是将扩展行为的变量抽象出来,类本身的行为一直没有变化,主要都是接受抽象出来的类进行变化,保证可变量才能变。这种明显比第一种方案更为优越。但是理解和拆分也更有难度。
依赖注入与数据驱动方式的区别
依赖注入和数据驱动的两种改造方案非常相似,主要方案就是将变的内容抽离到类的外部,区别主要在于依赖注入主要是抽离类,通过类的变化来控制行为变化,而数据驱动抽离的是数据内容。
数据驱动的特点
与继承和依赖注入方式相比,数据驱动更简洁,不需地定义额外的类,但是同样也不缺点,也就是数据都是既定的内容,如果是传入的内容本身就是一种形态,数据的方案也就不可靠了。在使用中可以认为,如果是既定内容,可以简单的使用数据驱动来做,如果是某种类型,使用扩展类(依赖注入、类继承)的方式更好用。
Liskov Substitution Principle 里氏替换原则
特点
- 继承、多态与封装,属于面向对象编程的几大核心特征。里氏替换原则对继承有指导意义。
- 使用继承时,子类对象应该可以在程序中替代父类对象使用,而不破坏程序原本的功能。
- 尽量将可变的行为做为类的一个属性(可变),并提供方法可以修改这个行为。
- 需要让子类方法和父类方法返回同一类型的结果,支持同样的操作。或者更进一步,返回支持更多种操作的子类型结果也是可以授受的。
- 子类方法参数应该和父类方法同名方法完全一致,或者更为宽松。
Interface Segregation Principle 接口隔离原则
什么是接口
接口是模块间相互交流的抽象协议。
遵守的原则
- 客户(client)应该不依赖于它不使用的方法。
- 一个接口所提供的方法,应该就是使用方所需要的方法。而更多的接口方法意味着更高的实现成本,给实现方带来更多的出错机率。
- 让客户(调用方)来驱动协议设计。在有多余的依赖时,找出最小类,然后依据不同的依赖关系,继承出更小的类。
Dependency Inversion Principle 依赖倒置原则
特征
- 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
- 通过编写测试反向推动设计改进。
- 抽象解耦了高层模块和低层模块间的依赖关系,让代码更灵活。但抽象同时也带来了额外的编程与理解成本。而只有对代码中现在或者未来会发生变化的东西进行抽象,才能获得最大的利益。