设计原则
开闭原则OCP
软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改
解读话语:对修改关闭,对扩展开放。修改一词具有一定的歧义,并不是说完全杜绝修改,而是以最小的修改代码的代价完成新功能的开发。同样的代码改动,在粗代码粒度下,可能被认定为修改,在细代码粒度下,可能被认定为扩展。
解决方案:要时刻具备扩展意识、抽象意识和封装意识。但是不要为了实现原则而过度设计。
单一职责原则SRP
就一个类而言,应该仅有一个引起它变换的原因。
解读话语:一个类或者模块只负责完成一个职责(或者功能)。不要设计大而全的类,要设计粒度小、功能单一的类。单一职责原因是为了实现代码高内聚、低耦合,提高代码的复用性、可读性和可维护性。但是如果拆分的过细,实际上会适得其反,会降低内聚性,也会影响代码的可维护性。
解决方案:违反单一职责案例
- 类中的代码行数、函数或者属性过多
- 类依赖的其他类过多,或者依赖类的其他类过多
- 私有方法过多
- 比较难给类起一个合适的名字
- 类中大龄的方法都是集中操作类的某几个属性
迪米特法则LOD
德墨忒尔定律
又叫最少知道原则,只和你的密友谈话,不和陌生人谈话。
解读话语:
- 每个单元对于其他的单元只能拥有有限的知识,只是与当前当前单元紧密联系的单元
- 每个单元只能和它的朋友交谈,不能和陌生单元交谈
- 只和自己直接的朋友交谈。
- 不该有直接依赖关系的类之间不要有依赖,有依赖关系的类之间,尽量只依赖必要的接口(有限知识)
解决方案:减少类之间的耦合,让类越独立越好。每个类都应该少了解系统的其他部分。
接口隔离原则ISP
不应该强迫用户依赖于他们不同的方法,接口属于客户,不属于他所在的类层次结构。
解读话语:接口的粒度要尽可能的小,客户只需要知道他们感兴趣的接口。
跟单一职责原则的比较:
- 单一职责原则针对的是模块、类、接口的设计
- 接口隔离原则更侧重于接口的设计,提供了一种判断接口的职责是否单一的标准,通过调用者如何使用接口来间接地判定。
里氏替换原则LSP
子类型必须能替换掉他们的基本类型(父类型)
解读话语:子类对象能能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏,是继承的指导原则。
解决方案:按照协议来设计。
- 子类不能违背父类声明要实现的功能
- 子类不能违背父类对输入、输出、异常的约定
- 子类不能违背父类注释中所罗列的任何特殊说明
依赖倒置原则DIP
抽象不应该依赖于细节,细节应该依赖于抽象
针对接口编程,而不是针对实现编程。
解读话语:
- 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口
- 抽象接口不应该依赖于具体实现,而具体实现则应该依赖于抽象接口
组合复用原则CRP
优先使用对象组合,而不是类继承。
解读话语:组合优于继承,能使用组合就尽量少用继承。
DRY原则
不要重复自己
解读话语:同样的功能业务代码不要重复出现,提高可复用性。
解决方案:
- 减少代码耦合
- 满足单一职责原则
- 模块化
- 业务与非业务逻辑分离
- 通用代码下沉
- 继承、多态、抽象和封装
- 应用模板等设计模式
KISS原则
尽量保持简单
解读话语:功能实现遵循简单就是王道
解决方案:
- 不要使用同事可能不懂的技术来实现代码
- 不要重复造轮子,要善于使用已经有的工具类库
- 不要过度优化
YANGI
原则
你不会需要它
解读话语:不要去设计当前用不到的功能,不要去编写当前用不到的代码,不要过度设计。
解决方案:遇到需求不要过分解读,遵循目前已有的需求就好。遇到需求变更再考虑重构,以不变应万变。
总结:
设计原则是总的指导方针,都是围绕高内聚和低耦合,提高代码的可维护性、可扩展性,我们要适当的使用设计原则,不要过度解读某一种或某几种设计原则,只要是能写出好的代码(可读、可维护、可扩展、可复用的代码)就行。