第一章.设计原则-----最少知识原则

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haochangdi123/article/details/85598803

最少知识原则也叫迪米特法则(Law of Demeter,LoD),“迪米特”这个名字源自 1987 年美国东北大学一个名为“Demeter”的研究项目。

许多人更倾向于使用迪米特法则这个名字,也许是因为显得更酷一点。但本书参考 Head First Design Patterns 的建议,称之为最少知识原则。一是因为这个名字更能体现其含义,另一个原因 是“法则”给人的感觉是必须强制遵守,而原则只是一种指导,没有哪条原则是在实际开发中必 须遵守的。比如,虽然遵守最小知识原则减少了对象之间的依赖,但也有可能增加一些庞大到难 以维护的第三者对象。跟单一职责原则一样,在实际开发中,是否选择让代码符合最少知识原则, 要根据具体的环境来定。

最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这 里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。

我们先来看一下这个代码:

gerneral.getColonel(c).getMajor(m).getCaptain(c).getSergeant(s).getPrivate(p).digFoxhole();

代码通过这么长的消息链才能完成一个任务,太过于繁琐!而且,这条链中任何一个对象的改动都会影响整条链的结果。

1. 减少对象之间的联系

单一职责原则指导我们把对象划分成较小的粒度,这可以提高对象的可复用性。 但越来越多的对象之间可能会产生错综复杂的联系,如果修改了其中一个对象,很可能会影响到跟它相 互引用的其他对象。对象和对象耦合在一起,有可能会降低它们的可复用性。

最少知识原则要求我们在设计程序时,应当尽量减少对象之间的交互。 如果两个对象之间不必彼此直接通信,那么这两个对象就不要发生直接的相互联系。常见的做法是引入一个第三者对象,来承担这些对象之间的通信作用。如果一些对象需要向另一些对象发起请求,可以通过第三 者对象来转发这些请求。

2.设计模式中的最少知识原则

最少知识原则在设计模式中体现得最多的地方是中介者模式和外观模式,下面我们分别进行介绍。

2.1 中介者模式

简单来说和房产中介很像,中介收集许多房源,向许多需要房子的客户介绍房子。这样一来需要房子的人和房主就不需要直接联系。

中介者模式很好地体现了最少知识原则。通过增加一个中介者对象,让所有的相关对象都通过中介者对象来通信,而不是互相引用。所以,当一个对象发生改变时,只需要通知中介者对象即可。

2.2 外观模式

外观模式在 JavaScript 中的使用场景并不多。外观模式主要是为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个 接口使子系统更加容易使用。

在这里插入图片描述

当子系统的复杂性很高时,外观模式对客户提供一个简单易用的高层接口,高层接口会把客户的请求转发给子系统来完成具体的功能实现。

当然客户也可以选择越过外观来直接访问子系统。

外观模式容易跟普通的封装实现混淆。 这两者都封装了一些事物,但外观模式的关键是定义 一个高层接口去封装一组“子系统”。子系统在 C++或者 Java 中指的是一组类的集合,这些类相互协作可以组成系统中一个相对独立的部分。在 JavaScript 中我们通常不会过多地考虑“类”,如果将外观模式映射到 JavaScript 中,这个子系统至少应该指的是一组函数的集合。

最简单的外观模式应该是类似下面的代码:

var A = function () {
      a1();
      a2();
}
var B = function () {
      b1();
      b2();
}
var facade = function () {
      A();
      B();
}
facade();

许多 JavaScript 设计模式的图书或者文章喜欢把 jQuery 的$.ajax 函数当作外观模式的实现, 这是不合适的。如果$.ajax 函数属于外观模式,那几乎所有的函数都可以被称为“外观模式”。 问题是我们根本没有办法越过$.ajax“外观”去直接使用该函数中的某一段语句。

现在再来看看外观模式和最少知识原则之间的关系,外观模式的作用主要有两点:

  1. 为一组子系统提供一个简单便利的访问入口。

  2. 隔离客户与复杂子系统之间的联系,客户不用去了解子系统的细节

从第二点来,外观模式是符合最少知识原则的。客户不用去了解这些子系统的具体实现。

通过外观 将客户和这些子系统隔开之后,如果修改子系统内部,只要外观不变,就不会影响客户的调用。 同样,对外观的修改也不会影响到子系统,它们可以分别变化而互不影响。

3. 封装在最少知识原则中的体现

封装在很大程度上表达的是数据的隐藏。 一个模块或者对象可以将内部的数据或者实现细节隐藏起来,只暴露必要的接口 API 供外界访问。对象之间难免产生联系,当一个对象必须引 用另外一个对象的时候,我们可以让对象只暴露必要的接口,让对象之间的联系限制在最小的 范围之内。

同时,封装也用来限制变量的作用域。在 JavaScript 中对变量作用域的规定是:

  1. 变量在全局声明,或者在代码的任何位置隐式申明(不用 var),则该变量在全局可见;
  2. 变量在函数内显式申明(使用 var),则在函数内可见。

把变量的可见性限制在一个尽可能小的范围内,这个变量对其他不相关模块的影响就越小,
变量被改写和发生冲突的机会也越小。这也是广义的最少知识原则的一种体现。

参考资料

JavaScript设计模式与开发实践----曾探

猜你喜欢

转载自blog.csdn.net/haochangdi123/article/details/85598803