1.职责链模式是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象形成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
举例说明:中学时代期末考试,如果你平时不太老实,考试将会被安排在第一个位置,遇到不会打的题目,就把题目编号写在小纸条上往后传递,坐在后面的同学如果不会,也会继续往后传
职责链模式的优点:请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接收者的强联系
代码实现(假设我们有一个售卖手机的电商网站,经过分别交纳500和200元定金的两轮预定后,订单在此时生效,到正式购买阶段。在正式购买后,已经支付过500的用户会收到100元的券,支付过200的获得50券,而之前没有支付过的用户只能进入普通购买模式,且在库存有限的情况下)
//1.orderType:订单类型(定金或者普通用户)code为1是500定金用户,code为2是200定金用户,为3是普通用户
//2.pay:表示用户是否已经支付定金,用户可能下了500的订单,但是没有支付定金
//3.stock:手机库存
function order(orderType,pay,stock){
switch(orderType){
case 1:
if(pay){
console.log("500,返100")
}else{
if(stock > 0){
console.log("普通用户,可以购买")
return;
}else{
console.log("手机库存不足")
}
}
break;
case 2:
if(pay){
console.log("200,返50")
}else{
if(stock > 0){
console.log("普通用户,可以购买")
}else{
console.log("手机库存不足")
}
}
break;
case 3:
if(orderType === 3){
if(stock > 0){
console.log("普通用户,可以购买")
}else{
console.log("手机库存不足")
}
}
}
}
order(1,true,20)//虽然我们得到了意料中运行结果,但这段代码巨大难以阅读
代码实现2使用职责链重构代码 将500、200以及普通用户分为三个函数
function order500(orderType,pay,stock){
if ( orderType === 1 && pay === true ){
console.log( '500 ,返100券' );
}else{
order200( orderType, pay, stock ); // 将请求传递给 200 元订单
}
}
function order200( orderType, pay, stock ){
if ( orderType === 2 && pay === true ){
console.log( '200 ,返50券' );
}else{
orderNomarl( orderType, pay, stock ); // 将请求传递给 200 元订单
}
}
function orderNomarl(orderType, pay, stock ){
if(stock > 0){
console.log("普通用户,可以购买")
}else{
console.log("手机库存不足")
}
}
order500(1,false,200) //普通用户,可以购买
//我们已经把大函数拆分成了互不影响的3个小函数,但请求在链条中的传递顺序很僵硬,传递请求别耦合在了业务函数中
var order500 = function( orderType, pay, stock ){
if ( orderType === 1 && pay === true ){
console.log( '500 元定金预购, 得到 100 优惠券' );
}else{
order200( orderType, pay, stock );
// order200 和 order500 耦合在一起 如果有天我们要增加300或者去掉200的订单则需要改动这些业务函数内部
}
};
代码实现3.灵活可拆分的职责链节点,我们约定摸个节点不能处理请求的时候返回一个特殊的字符串“nextSuccessor”,表示该请求需要继续往后传递
function order500(orderType,pay,stock){
if ( orderType === 1 && pay === true ){
console.log( '500 ,返100券' );
}else{
return 'nextSuccessor';
}
}
function order200( orderType, pay, stock ){
if ( orderType === 2 && pay === true ){
console.log( '200 ,返50券' );
}else{
return 'nextSuccessor';
}
}
function orderNomarl(orderType, pay, stock ){
if(stock > 0){
console.log("普通用户,可以购买")
}else{
console.log("手机库存不足")
}
}
//接下来需要把函数包装进职责链节点,我们定义一个构造函数Chain,在new Chain的时候传递的参数即为需要被包装的函数,同时它还拥有一个实例属性this.successor,百表示在链中的下一节点
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;
}
//将三个订单函数分别包装成职责链节点
var chainOrder500 = new Chain( order500 );
var chainOrder200 = new Chain( order200 );
var chainOrderNormal = new Chain( orderNomarl );
//然后指定节点子职责链中的顺序
chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainOrderNormal);
//最后把请求传给一个节点
chainOrder500.passRequest(2,false,500)
总结:无论是在作用域链、原型链、还是DOM节点中的事件冒泡,我们都能从中找到职责链模式的影子。
网友评论