Skip to content

Latest commit

 

History

History
148 lines (137 loc) · 5.03 KB

10职责链模式.md

File metadata and controls

148 lines (137 loc) · 5.03 KB

职责链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

优点:

  • 解耦合:职责链模式的最大优点就是解耦了请求发送者和 N 个接收者之间的复杂关系(1对多 -> 1对1对1...)
  • 任意起始点
  • 组织代码

缺点:

  • 多余的节点对象,用来帮助传递,并无实质性作用
  • 性能:过长的职责链,会使调用栈的叠加,导致性能问题

故事背景

假设我们负责一个售卖手机的电商网站,经过分别交纳 500 元定金和 200 元定金的两轮预定后(订单已在此时生成),现在已经到了正式购买的阶段。公司针对支付过定金的用户有一定的优惠政策。 在正式购买后,已经支付过 500 元定金的用 户会收到 100 元的商城优惠券,200 元定金的用户可以收到 50 元的优惠券, 而之前没有支付定金的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。

代码实现(未使用职责链模式)

var order = function( orderType, pay, stock ){
    if ( orderType === 1 ){ // 500 元定金购买模式
        if ( pay === true ){ // 已支付定金
            console.log( '500 元定金预购, 得到 100 优惠券' );
        } else{ // 未支付定金,降级到普通购买模式
            if ( stock > 0 ){ // 用于普通购买的手机还有库存
                console.log( '普通购买, 无优惠券' );
            }else{
                console.log( '手机库存不足' );
            } 
        }
    } else if ( orderType === 2 ){ 
        if ( pay === true ){ // 200 元定金购买模式
            console.log( '200 元定金预购, 得到 50 优惠券' ); 
        }else{
            if ( stock > 0 ){
                console.log( '普通购买, 无优惠券' );
            }else{
                console.log( '手机库存不足' );
            } 
        }
    } else if (orderType === 3) {
        if ( stock > 0 ){
            console.log( '普通购买, 无优惠券' ); 
        } else{
            console.log( '手机库存不足' ); 
        }
    } 
};
order( 1 , true, 500); // 输出: 500 元定金预购, 得到 100 优惠券

代码重构(使用职责链模式)

var Chain = function( fn ){
    this.fn = fn;
    this.successor = null; 
};
// 指定在链中的下一个节点
Chain.prototype.setNextSuccessor = function( successor ){ 
    return this.successor = successor;
};
Chain.prototype.next = function( successor ){ 
    return this.successor && this.successor.passRequest.apply( this.successor, arguments );
};
// 传递请求给某个节点
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 order500 = function( orderType, pay, stock ){ 
    if ( orderType === 1 && pay === true ){
        console.log( '500 元定金预购,得到 100 优惠券' ); 
    } else{
        return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递 
    }
};
var order200 = function( orderType, pay, stock ){ 
    if ( orderType === 2 && pay === true ){
        console.log( '200 元定金预购,得到 50 优惠券' ); 
    } else{
        return 'nextSuccessor'; // 我不知道下一个节点是谁,反正把请求往后面传递 
    }
};
var orderNormal = function( orderType, pay, stock ){
    if ( stock > 0 ){ 
        console.log( '普通购买,无优惠券' ); 
    } else{
        console.log( '手机库存不足' ); 
        return 'nextSuccessor'
    }
};

var chainOrder500 = new Chain( order500 );
var chainOrder200 = new Chain( order200 );
var chainOrderNormal = new Chain( orderNormal );
var fn2 = new Chain(function(){ 
    console.log( 2 );
    var self = this; 
    setTimeout(function(){
        self.next(); 
    }, 1000 );
});
var fn3 = new Chain(function(){
    console.log( 3 );
});

chainOrder500
  .setNextSuccessor( chainOrder200 )
  .setNextSuccessor( chainOrderNormal)
  .setNextSuccessor( fn2 )
  .setNextSuccessor( fn3 )

chainOrder500.passRequest(3, true, 0)

用AOP实现职责链

var fn1 = function(){
   console.log( 1 );
   return false;
}
var fn2 = function(){
   console.log( 2 );
   return false;
}
var fn3 = function(){
   console.log( 3 );
   return false;
}
Function.prototype.after = function( fn ){ 
    var self = this;
    return function() {
        var ret = self.apply( this, arguments ); 
        if ( ret === false ){
            return fn.apply( this, arguments ); 
        }
        return ret; 
    }
};

var order = fn1.after( fn2 ).after( fn3 );
order();

用 AOP 来实现职责链既简单又巧妙,但这种把函数叠在一起的方式,同时也叠加了函数的 作用域,如果链条太长的话,也会对性能有较大的影响