单一职责原则(SRP):Single Responsibility Principle
A class should have one and only one reason to change, meaning that a class should have only one job.
一个类应该有一个且只有一个改变的原因,这意味着一个类应该只有一个职责。
职责有粒度之分,有层级之别,当系统越复杂,一个类的职责应该越单一,以提高类的透明度,便于维护。
好比在小公司,一个人可能身兼数职,因为事情少,负责多件事也能应付,主要是可以减少人力成本。如果在大公司,职级体系全面,每个人都有固有职责,这样更便于管理。
所以这里面有个权衡问题,如果业务简单,划分出太多的类完全没必要,如果要构建复杂体系,单一职责就很有必要。
开闭原则(OCP):Open-Closed Principle
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
软件实体(类、模块、函数等)都应当对扩展具有开放性,但是对于修改具有封闭性。
Spring框架就是开闭原则最具体的体现,它里面有很多的扩展点,基本上不需要对源码进行修改。想对扩展开放,抽象必不可少,spring里接口无处不在。在具体项目时,还是需要权衡,过多的抽象虽然能提高扩展性,但同时也增加复杂性。很多时候,我们并不能很好的对功能做出合理的抽象,就像在写service层的代码时,经常会有变动,接口类反而会增加额外的维护负担。
总而言之,对功能进行合理适度的抽象(或封装)是很有必要的,只有这样,我们才能很淡定的拥抱需求的变化。
里氏替换原则(LSP):Liskov Substitution Principle
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.所有引用基类的地方必须能透明地使用其子类对象。
子类应该是具有父类的一切特征,在引用父类的地方应该可以无缝替换成子类。
言下之意是子类应尽可能在去继承,而不是去覆盖父类的方法。换个角度来看,也就是说父类中的方法应该具有普适性,不应该存在以偏概全的情况。
迪米特法则(LOD):Law of Demeter
Talk only to your immediate friends and not to strangers
只和你的直系朋友说话,不要和陌生人说话
迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。
这个原则初衷应该是尽可能减少对其他类的依赖,即使有依赖,我们也要通过靠谱的对象进行转达。个人觉得网关比较适合这个原则,前端对后台服务的访问都走网关,它不需要知道提供服务的应用具体是哪个。
接口隔离原则(ISP):Interface Segregation Principle
A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use.
永远不要强迫客户端实现它不使用的接口,也不要强迫客户端依赖它们不使用的方法。
接口本身应该符合单一职责原则(SRP),不应过于臃肿,要有一定的边界。在JAVA中对接口是可以多继承的,比如spring中对象的生命周期接口,就可以通过多继承的方式来实现。换句话说,就是可以根据需求来实现不同的接口,不需要冗余不需要的空接口。
依赖倒置原则(DIP):Dependency Inversion Principle
Entities must depend on abstractions, not on concretions. It states that the high-level module must not depend on the low-level module, but they should depend on abstractions.
实体必须依赖于抽象,而不是具体实现。它指出高级模块不能依赖于低级模块,而应该依赖于抽象。
这个原则应该就是对面向接口编程的归纳,为什么要面向接口编程? 如果想构建复杂的系统,定然要采用分治思维,将系统划分为不同的模块,那模块之间要靠什么进行互通?就是靠接口。接口可以屏蔽模块的底层细节,其他模块无须关注实现细节,只需按照接口规约进行调用就可以得到需要的答案。从另一个角度来看,接口的质量很重要,需要保持相对稳定。