定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
**职责连是由多个不同的对象组成的,发送者是发送请求的对象,接收者接收请求并且对其进行处理或传递的对象。基本流程如下:
- 发送者知道链中的第一个接收者,它向这个接收者发送该请求。
- 每一个接收者都对请求进行分析,然后要么处理它,要么它往下传递。
- 每一个接收者知道其他的对象只有一个,即它在链中的下家(successor)。
- 如果没有任何接收者处理请求,那么请求会从链中离开。
职责链模式是个链式结构,请求在链中的节点之间依次传递,直到有一个对象能处理该请求为止。如果没有任何对象处理该请求的话,那么请求就会从链中离开。
demo
参考链接
这个例子并不好但是可以帮助我们理解职责链这种设计模式
以电商网站抽奖为例,规则如下:
- 用户充值>=500元,可以100%中奖100元红包
- 用户充值>=200元,可以100%中奖20元红包
- 用户不充值,也可以抽奖,但概率极低。
- 用户充值失败,按不充值处理。
注意的是
用户充值之后的如果大于500是100&中奖的,而大于200时是100%中20,当然也应该先有可能中20的,所以一般的流程就规定了先从500往下判断,当然可以先判断是否充值成功;
参数讲解
/*** 用户抽奖* @param orderType 1:500 2:2000* @param isPay 充值是否成功* @param count 充值金额*/
面向过程
var order = function(orderType,isPay,count) {if(isPay === true){ //如果充值成功的话if(orderType === 1) // 用户充值500元 100%中奖console.log("亲爱的用户,您中奖了100元红包了");else if(orderType === 2)// 用户充值200元 100%中奖console.log("亲爱的用户,您中奖了20元红包了");}else {if(count > 0) {console.log("亲爱的用户,您已抽到10元优惠卷");}else {console.log("亲爱的用户,请再接再厉哦");}}};
职责链实现
定义三种方法(结果)
function order500(orderType,isPay,count){if(orderType === 1 && isPay === true) {console.log("亲爱的用户,您中奖了100元红包了");}else {//我不知道下一个节点是谁,反正把请求往后面传递return "nextSuccessor";}}function order200(orderType,isPay,count) {if(orderType === 2 && isPay === true) {console.log("亲爱的用户,您中奖了20元红包了");}else {//我不知道下一个节点是谁,反正把请求往后面传递return "nextSuccessor";}}function orderNormal(orderType,isPay,count){// 普通用户来处理中奖信息if(count > 0) {console.log("亲爱的用户,您已抽到10元优惠卷");}else {console.log("亲爱的用户,请再接再厉哦");}}
职责链
class Chain{constructor(fn){this.fn = fn;this.successor = null;}// 设置下一个节点setNextSuccessor(successor){return this.successor = successor;};// 把请求往下传递passRequest(){let ret = this.fn.apply(this,arguments);// 需要进行下一节点if(ret === 'nextSuccessor') {return this.successor && this.successor.passRequest.apply(this.successor,arguments);}return ret;}}
调用
//现在我们把3个函数分别包装成职责链节点:var chainOrder500 = new Chain(order500);var chainOrder200 = new Chain(order200);var chainOrderNormal = new Chain(orderNormal);// 然后指定节点在职责链中的顺序chainOrder500.setNextSuccessor(chainOrder200);chainOrder200.setNextSuccessor(chainOrderNormal);//最后把请求传递给第一个节点:chainOrder500.passRequest(1,true,500); // 亲爱的用户,您中奖了100元红包了chainOrder500.passRequest(2,true,500); // 亲爱的用户,您中奖了20元红包了chainOrder500.passRequest(3,true,500); // 亲爱的用户,您已抽到10元优惠卷chainOrder500.passRequest(1,false,0); // 亲爱的用户,请再接再厉哦
