职责链模式
定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
优缺点
职责链模式的优点:
- 和命令模式类似,由于处理请求的职责节点可能是职责链上的任一节点,所以请求的发送者和接受者是解耦的;
- 通过改变链内的节点或调整节点次序,可以动态地修改责任链,符合开闭原则;
职责链模式的缺点:
- 并不能保证请求一定会被处理,有可能到最后一个节点还不能处理;
- 调试不便,调用层次会比较深,也有可能会导致循环引用;
示例
1.异步的职责链
var Chain = function(fn) {
this.fn = fn;
this.successor = null;
};
// 指定在链中的下一个节点
Chain.prototype.setNextSuccessor = function(successor) {
return this.successor = successor;
};
// 传递请求给某个节点
Chain.prototype.passRequest = function() {
var ret = this.fn.apply(this, arguments);
if(ret === "nextSuccessor") {
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
}
return ret;
};
Chain.prototype.next = function() {
return this.successor && this.successor.passRequest.apply(this.successor, arguments);
};
var fn1 = new Chain(function(){
console.log("fn1");
return "nextSuccessor";
});
var fn2 = new Chain(function(){
console.log("fn2");
var self = this;
setTimeout(function(){
self.next();
}, 1000);
});
var fn3 = new Chain(function(){
console.log("fn3");
});
fn1.setNextSuccessor(fn2).setNextSuccessor(fn3);
fn1.passRequest();
2.用Aop实现职责链
Function.prototype.after = function(fn) {
var self = this;
return function(){
var ret = self.apply(this, arguments);
return ret ? fn.apply(this, arguments) : false;
}
};
var fn1 = function() {
console.log("fn1");
return true;
}
var fn2 = function() {
console.log("fn2");
return true;
}
var fn3 = function() {
console.log("fn3");
return true;
}
var chainAfter = fn1.after(fn2).after(fn3);
if(!chainAfter()) {
console.log("不通过。")
} else {
console.log("通过。")
}
总结
在 JavaScript 开发中,职责链模式是最容易被忽视的模式之一。实际上只要运用得当,职责链模式可以很好地帮助我们管理代码,降低发起请求的对象和处理请求对象之间的耦合性。职责链中的节点数量和顺序是可以自由变化的,我们可以在运行时决定链中包含哪些节点。