职责链模式是从链式编程中延伸出来的一种(行为型)设计模式。为了更好理解职责链,本文先从链式编程开始介绍。
链式编程
和函数式编程不同[1],所谓的链式编程就是可以通过"点"语法,将需要执行的代码块连续的书写下去,使得代码简单易读,书写方便。在JQuery中早就有了这个概念。如下图: 图片资源来自[2]函数编程式中的链式优化[3]
一个计算器中要根据各种运算符计算结果,我们常常这样实现(极端例子):
function add(a, b){
return a + b
}
function multiply(a, b){
return a * b
}
//计算 ( 1 + 1 ) * 2
multiply( add(1, 1), 2 )
//计算 ( 1 + 1 ) * 2 + 3
add( multiply( add(1, 1), 2 ) )
上述代码中仅仅多了一个“+3”运算 ,整个函数都要外部多包一层,且在语义化上非常难读,在这种情况下,我们可以考虑多种优化方式,比如下面的 链式优化 。
const utils = {
chain(a) {
this._temp = a;
return this;
},
add(b) {
this._temp += b;
return this;
},
multiply(b) {
this._temp *= b;
return this;
},
value() {
const _temp = this._temp;
this._temp = undefined;
return _temp;
}
};
//计算 ( 1 + 1 ) * 2
utils.chain(1).add(1).multiply(2)
//计算 ( 1 + 1 ) * 2 + 3
utils.chain(1).add(1).multiply(2).add(3)
职责链模式
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间 的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。[4]
职责链的一个例子是事件冒泡:事件通过一系列嵌套控件传播,其中控件可以选择处理事件。
图解
image对象模型
- Client -- 示例代码:
Request
- 向一系列处理程序对象发起请求
- Handler -- 示例代码:
Request.get() method
- 定义用于处理请求的接口
- 实现后继链接用于传递(return 'this')
JavaScript中的示例代码[5]
此示例展示了一种优化后的点钞机问题解决方案。比如,客户从一台ATM机取247元,如何组合钞票(100元,50元,20元,10元,5元,1元)满足这一需求。
var Request = function(amount) {
this.amount = amount;
}
Request.prototype = {
get: function(bill) {
var count = Math.floor(this.amount / bill);
this.amount -= count * bill;
return this;
}
}
function run() {
var request = new Request(378);
request.get(100).get(50).get(20).get(10).get(5).get(1);
}
参考
- [1] 链式编程与函数式编程区别
- [2] 如何在JavaScript中编写类似于jQuery的链接函数?
- [3] 函数编程式中的链式优化
- [4] [JavaScript设计模式与开发实践][M] p.198
- [5] 职责链模式案例
网友评论