JavaScript设计模式笔记(零)设计模式的原则
设计模式是设计于解决某些特定情况,但解决这些特定情况的设计,也需要遵循一定的原则
单一职责原则(SRP)
基本定义
单一职责原则体现在一个对象/方法只有一个职责,即只完成一件事,当我们要修改这个对象/方法时,只能是我们要对这件事的“做法”进行修改,而如果一个对象/方法有两个职责,那我们可能就有两个理由去修改这个对象/方法了。
目的
单一职责原则的目的在于减少耦合,方便我们对代码的修改,假设多个职责耦合在一个对象/方法内,当我们要修改一个职责时,很可能会影响到其他职责的正常实现。
设计模式中的单一职责原则
1.代理模式
代理模式将原对象要完成的另一件事委托给代理类完成,这样代理类和原对象可以保持只有一个职责,如果还有新的事件,也可以代理给新的对象。
2.装饰者模式
装饰者模式和代理模式类似,我们可以通过装饰链来将多个职责放在新添加的装饰对象上,这样也能保持每个对象只有一个职责。
单一职责的“单一”
单一职责的“单一”指的也不一定是非要只有一个职责,当我们确定两个职责是关联的时候,我们可以将这两个职责放在同一个对象/方法中,这样也可以减少对象的创建。
开放-封闭原则
基本定义
当需要改变一个程序的功能或者给这个程序增加新的功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码。
—–曾探的《JavaScript设计模式与开发实践》
消除条件分支语句
条件分支语句是违背开放-封闭原则的一个常见原因,诸如if-else,switch-case,当我们要增加新的条件时,总是会被迫去修改原函数,条件分支的违反情况如下代码(源自《JavaScript设计模式与开发实践》)
1 |
|
这里当我们添加一个Dog的叫声后,必须进入原来的函数中修改if-else语句才能达到我们要的结果,这显然违背了开放-封闭原则。
在这个例子中,我们要实现开放-封闭原则,首先要明确哪些是可变哪些是不可变的,将可变的部分作为参数传入,而不可变的部分封装在函数内部,这样当我们修改可变部分时就可以不修改函数内部的功能实现代码。
这里可变的是动物的种类,而且判断的种类也是可变的,因此此时我们传入的是一个对象,可以将功能放在对象的原型上,在方法内部调用传入对象的固定某个方法,而每个对象的方法又不一,这样就可以实现在不违法开放-封闭原则情况下增加功能。这正是对象的多态思想。
1 |
|
可以看到这里虽然添加了狗的叫声,但是我们对方法内部的代码没有进行任何修改。
总结上面的内容,我们可以看到,开放-封闭原则其实就是将可变的部分放在方法外修改,而将不可变的部分封装起来。
设计模式中的开放-封闭原则
事实上,几乎所有的设计模式都遵循开放-封闭原则,所以这里我们来提提这个原则在几个模式中的特别体现
1.发布-订阅模式
在发布-订阅模式中,订阅方向发布方发起订阅,当有新的订阅方订阅发布方时,此时不需要修改发布方也不需要修改之前的订阅方。
2.策略模式
在策略模式中每种策略都是独立的,新增一个策略不用修改之前的策略。
3.代理模式
通过代理将职责交给代理方完成,原对象的内容不用做修改。
4.职责链模式
职责链上每个节点的功能是独立的,即使往其上添加新的职责链节点,也不会修改之前的节点内容。
5.装饰者模式
装饰者模式在原对象的功能上新增新的对象而不修改原对象的内容,正好符合开放-封闭原则
相对的开放-封闭
正如《JavaScript设计模式与开发实践》里面所写的,
让程序保持完全封闭是不容易做到的,即使技术上做得到,也需要花费太多的时间和精力。
上面提到的符合开放-封闭原则的设计模式,也只是在其中的一部分符合开放-封闭原则,就如策略模式虽然新增一个策略不会修改之前的策略,但是策略方这个对象已经被修改是不争的事实,我们应该在可以不花过多时间和精力的条件下实现开放-封闭原则。
最少知识原则
基本定义
最少只是原则强调减少对象间的联系,所谓的知识,指的就是对其他对象的了解,而我们要尝试减少一个对象对其他对象的了解。
目的
最少知识原则的设置目的在于,当对象间的联系变多的话,我们修改其中一个对象,很可能会引起多个对象的变化,而这显然会引起我们维护的困难,我们无法轻易地修改其中一个对象,即使我们只是往对象中添加一行代码都可能会影响到其他多个对象。
模式中的最少知识原则
1.中介者模式
中介者模式可能是最能体现最少知识原则的一个模式了,中介者模式将多个对象和一个中介者进行联系,我们所需要维护的知识一个中介者和多个对象的关系,而多个对象之间的关系由中介者来管理,我们在修改其中某个对象时不用担心会影响到其他对象。
封装体现的最少知识原则
封装通过将部分内容隐藏起来,而只暴露一个接口与外界交流来实现,这样使得对象之间的联系得以缩小,体现了最少知识原则。
最少知识原则带来的弊端
事实上,没有哪个原则在每个设计中都能很好地体现,往往原则和设计模式都是在特定情况下实现的,而我们要自行判断在什么情况下使用什么设计模式和是否遵循原则,像上面的中介者模式,虽然减少了连接在中介者身上的对象之间的联系,但是我们需要对联系多个对象的中介者进行维护,当连接的对象多的时候,这就不是一个简单的工作了。
参考自曾探的《JavaScript设计模式与开发实践》