职责链模式
1. 职责链定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将对象连成一条链,并沿着这个链传递该请求,直到有一个对象处理它为止
2.职责链优点
请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接受者之间的强联系
3.职责链缺点
职责链模式使得程序中多了一些节点对象,在某次请求传递过程中,大部分节点并没有实质性作用,只是让请求传递下去,从性能方面考虑,要避免过长的职责链带来的性能耗损
4.职责链使用场景
4.1 基础例子
商城做活动,预付定金500且购买的客户可返现100,预付定金200且购买的客户可返现50,普通购买则没有返现且库存不够买不到。
//设置每个节点的操作,即每种用户对应的操作,如果不能该节点不能操作则传递给下一个节点。
var order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log("100")
} else {
return 'nextSuccessor'
}
}
var order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('50')
} else {
return 'nextSuccessor'
}
}
var order = function (orderType, pay, stock) {
if (stock > 0) {
console.log('buy')
} else {
console.log('lack')
}
}
//职责链,规定每个节点的下一个节点,执行本节点的函数
function Chain(fn) {
this.fn = fn
this.nextSuccessor = null
}
Chain.prototype.setNextSuccessor = function (successor) {
this.nextSuccessor = successor
}
Chain.prototype.passRequest = function () {
var ret = this.fn.apply(this, arguments)
if (ret === 'nextSuccessor') {
return this.nextSuccessor && this.nextSuccessor.passRequest.apply(this.nextSuccessor, arguments)
}
}
//把每个节点都放到职责链中
var chainOrder500 = new Chain(order500)
var chainOrder200 = new Chain(order200)
var chainOrder = new Chain(order)
//设置职责链的下一个节点
chainOrder500.setNextSuccessor(chainOrder200)
chainOrder200.setNextSuccessor(chainOrder)
//设定从某个职责链节点开始执行
chainOrder500.passRequest(1, true, 1)
4.2 异步职责链
//设置每个节点的操作,即每种用户对应的操作,如果不能该节点不能操作则传递给下一个节点。
var order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log("100")
} else {
return 'nextSuccessor'
}
}
var order200 = function (orderType, pay, stock) {
var self = this
setTimeout(function () {
self.next()
}, 1000)
// if (orderType === 2 && pay === true) {
// console.log('50')
// } else {
// return 'nextSuccessor'
// }
}
var order = function (orderType, pay, stock) {
if (stock > 0) {
console.log('buy')
} else {
console.log('lack')
}
}
//职责链,规定每个节点的下一个节点,执行本节点的函数
function Chain(fn) {
this.fn = fn
this.nextSuccessor = null
}
Chain.prototype.setNextSuccessor = function (successor) {
this.nextSuccessor = successor
}
Chain.prototype.passRequest = function () {
var ret = this.fn.apply(this, arguments)
if (ret === 'nextSuccessor') {
return this.nextSuccessor && this.nextSuccessor.passRequest.apply(this.nextSuccessor, arguments)
}
}
Chain.prototype.next = function () {
return (this.nextSuccessor) && this.nextSuccessor.passRequest.apply(this.nextSuccessor, arguments)
}
// 把每个节点都放到职责链中
var chainOrder500 = new Chain(order500)
var chainOrder200 = new Chain(order200)
var chainOrder = new Chain(order)
//设置职责链的下一个节点
chainOrder500.setNextSuccessor(chainOrder200)
chainOrder200.setNextSuccessor(chainOrder)
// 设定从某个职责链节点开始执行
chainOrder500.passRequest(1, false, 1)
这里需要增加一个next函数,手动传递到下一个节点。
4.3 用AOP实现职责链
var order500 = function (orderType, pay, stock) {
if (orderType === 1 && pay === true) {
console.log("100")
} else {
return 'nextSuccessor'
}
}
var order200 = function (orderType, pay, stock) {
if (orderType === 2 && pay === true) {
console.log('50')
} else {
return 'nextSuccessor'
}
}
var order = function (orderType, pay, stock) {
if (stock > 0) {
console.log('buy')
} else {
console.log('lack')
}
}
Function.prototype.after = function (fn) {
var self = this
return function () {
var ret = self.apply(this, arguments)
if (ret === 'nextSuccessor') {
return fn && fn.apply(this, arguments)
}
return ret
}
}
var func = order500.after(order200).after(order)
func(1, true, 3)
这里使用self变量存储上一个函数,func存储的是最后一个调用after返回的函数。一旦调用func函数,会先执行self保存的函数,会追根溯源一直到到最开始的self保存的函数order500。这里利用了闭包的特性保留了每一个self变量。整个函数的执行过程有点像倒序的递归。理解了过程也就会知道return ret这句代码是为后面的函数准备的~
5. 建议
如果某块功能中存在大量的if else可以考虑使用职责链模式
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。