# 单一职责原则(SRP)

职责被定义为“引起变化的原因”。如果我们有两个动机去改写一个方法,那么这个方法就具有两个职责。每个职责都是变化的一个轴线,如果一个方法承担了过 多的职责,那么在需求的变迁过程中,需要改写这个方法的可能性就越大。 此时,这个方法通常是一个不稳定的方法,修改代码总是一件危险的事情,特别是当两个职 责耦合在一起的时候,一个职责发生变化可能会影响到其他职责的实现,造成意想不到的破坏,这种耦合性得到的是低内聚和脆弱的设计。 因此,SRP 原则体现为: 一个对象(方法)只做一件事情。

# 用到SRP的设计模式

  • 代理模式
  • 迭代器模式
  • 单例模式

# 什么时候使用SRP?

一方面,如果随着需求的变化,有两个职责总是同时变化,那就不必分离他们。比如在 ajax 请求的时候,创建 xhr 对象和发送 xhr 请求几乎总是在一起的,那么创建 xhr 对象的职责和发送 xhr 请求的职责就没有必要分开。 另一方面,职责的变化轴线仅当它们确定会发生变化时才具有意义,即使两个职责已经被耦 合在一起,但它们还没有发生改变的征兆,那么也许没有必要主动分离它们,在代码需要重构的 时候再进行分离也不迟。

# SRP的优缺点

SRP 原则的优点是降低了单个类或者对象的复杂度,按照职责把对象分解成更小的粒度,这有助于代码的复用,也有利于进行单元测试。当一个职责需要变更的时候,不会影响到其他的职责。 但 SRP 原则也有一些缺点,最明显的是会增加编写代码的复杂度。当我们按照职责把对象分解成更小的粒度之后,实际上也增大了这些对象之间相互联系的难度。

# 最少知识原则(LKP)

最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。 单一职责原则指导我们把对象划分成较小的粒度,这可以提高对象的可复用性。但越来越多的对象之间可能会产生错综复杂的联系,如果修改了其中一个对象,很可能会影响到跟它相互引用的其他对象。对象和对象耦合在一起,有可能会降低它们的可复用性。

# 使用LKP的设计模式

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

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

封装在很大程度上表达的是数据的隐藏。一个模块或者对象可以将内部的数据或者实现细 节隐藏起来,只暴露必要的接口 API 供外界访问。对象之间难免产生联系,当一个对象必须引 用另外一个对象的时候,我们可以让对象只暴露必要的接口,让对象之间的联系限制在最小的范围之内。 把变量的可见性限制在一个尽可能小的范围内,这个变量对其他不相关模块的影响就越小, 变量被改写和发生冲突的机会也越小。这也是广义的LKP的一种体现

# 什么时候使用LKP

虽然遵守最小知识原则减少了对象之间的依赖,但也有可能增加一些庞大到难 以维护的第三者对象。在实际开发中,是否选择让代码符合最少知识原则, 要根据具体的环境来定。

# 开放封闭原则(OCP)

在面向对象的程序设计中,开放封闭原则(OCP)是最重要的一条原则。很多时候,一个程序具有良好的设计,往往说明它是符合开放封闭原则的。 当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码。

# 编写符合OCP代码的方法

过多的条件分支语句是造成程序违反开放封闭原则的一个常见原因。每当需要增加一个新 的 if 语句时,都要被迫改动原函数。实际上,每当我们看到一大片的 if 或者 swtich-case 语句时,第一时间就应该考虑,能否利用对象的多态性来重构它们。

# 利用多态的思想

利用对象的多态性来让程序遵守开放封闭原则,是一个常用的技巧。

# 码放置挂钩

放置挂钩(hook)也是分离变化的一种方式。我们在程序有可能发生变化的地方放置一个挂钩,挂钩的返回结果决定了程序的下一步走向。这样一来,原本的代码执行路径上就出现了一个 分叉路口,程序未来的执行方向被预埋下多种可能性。

# 使用回调函数

在 JavaScript 中,函数可以作为参数传递给另外一个函数,这是高阶函数的意义之一。在这 种情况下,我们通常会把这个函数称为回调函数。在 JavaScript版本的设计模式中,策略模式和命令模式等都可以用回调函数轻松实现。 回调函数是一种特殊的挂钩。我们可以把一部分易于变化的逻辑封装在回调函数里,然后把 回调函数当作参数传入一个稳定和封闭的函数中。当回调函数被执行的时候,程序就可以因为回 调函数的内部逻辑不同,而产生不同的结果。

# 开放封闭原则总结

开放封闭原则是一个看起来比较虚幻的原则,但我们还是能找到一些让程序尽量遵守开放封闭原则的规律,最明显的就是找出程序中将要发生变化的地方,然后把变化封装起来。 通过封装变化的方式,可以把系统中稳定不变的部分和容易变化的部分隔离开来。在系统的 演变过程中,我们只需要替换那些容易变化的部分,如果这些部分是已经被封装好的,那么替换起来也相对容易。而变化部分之外的就是稳定的部分。在系统的演变过程中,稳定的部分是不需要改变的。