1,单一职责原则
定义:应该有且仅有一个原因引起类的变更。
SRP的原话解释是:
There should never be more than one reason for a class to change.
总结一下单一职责原则有什么好处:
1、类的复杂性降低,实现什么职责都有清晰明确的定义。
2、复杂性降低,可读性提高。
3、可读性提高,更容易维护。
4、变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
最佳实践:
类的单一职责确实受非常多因素的制约,纯理论地来讲,这个原则是非常优秀的,但是现实有现实的难处,你必须去考虑项目工期、成本、人员技术水平、硬件情况、网络情况甚至有时候还要考虑政府政策、垄断协议等因素。
对于单一职责原则,建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
2、里氏替换原则
定义:所有引用基类的地方必须能透明地使用其子类的对象。
通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
里氏替换原则为良好的继承定义了一个规范,一句简单的定义包含了4层含义。
1.子类必须完全实现父类的方法
2.子类可以有自己的个性
3.覆盖或实现父类的方法时输入参数可以被放大
4. 覆写或实现父类的方法时输出结果可以被缩小
采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美!
3、 依赖倒置原则
三层含义:
1. 高层模块不应该依赖低层模块,两者都应该依赖其抽象。
2. 抽象不应该依赖细节。
3. 细节应该依赖抽象。
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
抽象是对实现的约束,对依赖者而言,也是一种契约,不仅仅约束自己,还同时约束自己与外部的关系,其目的是保证所有的细节不脱离契约的范畴,确保约束双方按照既定的契约(抽象)共同发展,只要抽象这根基线在,细节就脱离不了这个圈圈,始终让你的对象做到“言必信,行必果”。
依赖是可以传递的,A对象依赖B对象,B又依赖C,C又依赖D……生生不息,依赖不止,记住一点:只要做到抽象依赖,即使是多层的依赖传递也无所畏惧!
4、接口隔离原则
定义:客户端不应该依赖它不需要的接口
那依赖什么?依赖它需要的接口,客户端需要什么接口就提供什么接口,把不需要的接口剔除掉,那就需要对接口进行细化,保证其纯洁性。
接口尽量细化,同时接口中的方法尽量少。
这与单一职责原则不是相同的吗?错,审视角度不相同,单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少。
保证接口的纯洁性:
接口要尽量小;接口要高内聚;定制服务;接口设计是有限度的。
在实践中可以根据以下几个规则来衡量:
一个接口只服务于一个子模块或业务逻辑;
通过业务逻辑压缩接口中的public方法,接口时常去回顾,尽量让接口达到“满身筋骨肉”,而不是“肥嘟嘟”的一大堆方法;
已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理;
了解环境,拒绝盲从。每个项目或产品都有特定的环境因素,别看到大师是这样做的你就照抄。环境不同,接口拆分的标准就不同。
怎么准确地实践接口隔离原则?实践、经验和领悟!
5、迪米特法则
一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。
我的知识你知道得越少越好:
1. 只和朋友交流
一个类只和朋友交流,不与陌生类交流,不要出现getA().getB().getC().getD()这种情况。
2. 朋友间也是有距离的
尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private、package-private、protected等访问权限。
3. 是自己的就是自己的
在实际应用中经常会出现这样一个方法:放在本类中也可以,放在其他类中也没有错,那怎么去衡量呢?你可以坚持这样一个原则:如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。
4. 谨慎使用Serializable
一个类或接口在客户端已经变更了,而服务器端却没有同步更新,难道不是项目管理的失职吗?
6、开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
一个软件产品只要在生命期内,都会发生变化,既然变化是一个既定的事实,我们就应该在设计时尽量适应这些变化,以提高项目的稳定性和灵活性,真正实现“拥抱变化”。
开闭原则告诉我们应尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来完成变化,它是为软件实体的未来事件而制定的对现行开发设计进行约束的一个原则。
开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。
为什么要采用开闭原则:
首先,开闭原则非常著名。
其次,开闭原则是最基础的一个原则,前五个原则就是指导设计的工具和方法,而开闭原则才是其精神领袖。
最后,开闭原则是非常重要的,可通过以下几个方面来理解其重要性。
1. 开闭原则对测试的影响
2. 开闭原则可以提高复用性
3. 开闭原则可以提高可维护性
4. 面向对象开发的要求
(摘抄设计模式之禅,作下笔记。)