依赖倒置原则存在的真正意义是指,我们需要将一些对象解耦,它们的耦合关系需要达到当一个对象依赖的对象作出改变时,对象本身不需要更改任何代码。
这样的架构可以实现一种松耦合的状态的系统,因为系统中所有的组件,彼此之间都了解很少或者不需要了解系统中其余组件的具体定义和实现细节。它同时实现了一种可测试和可替换的系统架构,因为在松耦合的系统中,任何组件都可以被提供相同服务的组件所替换。
它意味着当你在定义你的抽象层代码时,不应当在客户端代码在实现抽象逻辑时,暴露一些客户端代码不需要使用或者关心的方法,接口要保持精简。
通用的接口往往会无意识的将自己和类的实现耦合在了一起,所以你应当尽量的避免这种情况的发生。在设计接口时,你应当时刻提醒自己,我是否需要使用所有在接口中声明的方法呢?如果不是的话,将接口细分为更多个更精简、更具体的接口。
简单的说:
A class or module should have one, and only one, reason to be changed. 一个类或者模块应当用于单一的,并且唯一的缘由被更改。单一职责的反例是“上帝对象”:
A God Object aka an Object that knows everything and does everything. 上帝对象,一个知道一切事情,完成一切事情的对象。 In object-oriented programming, a God object is an object that knows too much or does too much. The God object is an example of an anti-pattern. 在面向对象编程中,上帝对象指一个了解太情或者做太多事情的对象。上帝对象是反模式的一个典型。通俗地讲,单一职责就是一个类或模块只干一件事儿,太多的职责会导致耦合。单一职责跟“低耦合、高内聚”原则也是相通的。
开闭原则是什么?
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. 软件实体(类、模块、函数等)都应当对扩展具有开放性,但是对于修改具有封闭性。当你需要对已有代码作出一些修改时,请切记以下两点:
保持函数、类、模块当前它们本身的状态,或者是近似于它们一般情况下的状态(即不可修改性)使用组合的方式(避免使用继承方式)来扩展现有的类,函数或模块,以使它们可能以不同的名称来暴露新的特性或功能开闭原则所带来最有用的好处就是,当我们在实现我们的抽象层代码时,我们就可以对未来可能需要作出改变的地方拥有一个比较完整的设想,这样当我们真正面临改变时,我们所对原有代码的修改,更贴近于改变本身,而不是一味的修改我们已有的抽象代码。---- 也就是要预测未来可能的修改,留有扩展的余地。
充分贯彻开闭原则的另一个例子,便是插件与中间件架构,我们可以从三个角度来简单分析这种架构是如何运作的:
内核或者容器:往往是核心功能的实现的前提,一般会成为整个系统最核心的部分插件:在实现容器的基础上,往往一些核心功能都是以内置的插件实现的,并且,通过实现一套通用的网关类接口,我们可以使插件具有可插拔性,这样在需要新增特性和功能时,只需要实现新的插件并添加到容器即可,比如支持插件扩展功能的浏览器Chrome。中间件:中间件我们可以通过一个例子来说明,比如我们拥有一个请求 - 响应周期,我们可以通过中间件,在周期中添加中间业务逻辑,以便为应用程序提供额外的服务或横切关注点,比如Redux、express还有很多框架都支持这样的功能。这句话的意思是说,当我们在传递一个父抽象的子类型时,你需要保证你不会修改任何关于这个父抽象的行为和状态语义。
如果你不遵循里氏替换原则,那么你可能会面临以下问题:
类继承会变得很混乱,因此奇怪的行为会发生对于父类的单元测试对于子类是无效的,因此会降低代码的可测试性和验证程度迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。英文简写为: LoD.
迪米特法则可以简单说成:talk only to your immediate friends。 对于 OOD 来说,又被解释为下面几种方式:一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。
迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系 —— 这在一定程度上增加了系统的复杂度。
设计模式的门面模式(Facade)和中介模式(Mediator),都是迪米特法则应用的例子。