javascript职责链模式

      职责连模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
      实例:公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过500员定金的用户会收到100员的商城优惠券,200定金的用户可以收到50元的优惠券,没有支付定金的用户没有优惠券,且在库存有限的情况下不一定保证能买到。流程如下:
      var order = function( orderType, pay, stock){
           if( orderType === 1 ){
               if( pay === true ){
                    console.log( "500元定金预购,得到100优惠券" );
               }else{
                    if( stock > 0 ){
                         console.log( "普通购买,无优惠券" );
                    }else{
                         console.log( "手机库存不足" );
                    }
               }
           }else if( orderType === 2 ){
               if( pay === true ){
                    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优惠券

      虽然上面的代码能完成给定的任务,但却不是值得夸奖的代码。order函数不仅可读性差,而且需要经常进行修改。

      用职责链模式重构代码:

      //500元订单
      var order500 = function( orderType, pay, stock ){
           if( orderType === 1 && pay === true){
               console.log( "500元定金预购,得到100优惠券" );
           }else{
               order200( orderType, pay, stock );
           }
       }

       //200元订单
      var order200 = function( orderType, pay, stock ){
            if( orderType === 2 && pay === true){
                 console.log( "200元定金预购,得到50优惠券" );
            }else{
                 orderNormal( orderType, pay, stock );
            }
        }

       //普通订单
      var orderNormal = function( orderType, pay, stock){
           if( stock > 0 ){
                 console.log( "普通购买,无优惠券" );
           }else{
                console.log( "手机库存不足" );
           }
       }

       order500( 1, true, 500); // 输出:500元定金预购,得到100优惠券


       可以看出,执行结果和前面的order函数一样,但代码的结构已经清晰了很多,我们把一个大函数分拆成3个小函数,去掉了许多条件分支语句。

       但是,应该注意到的是请求在链条传递中的顺序非常僵硬,传递请求的代码呗耦合在了业务函数中。
       var order500 = function( orderType, pay, stock ){
           if( orderType === 1 && pay === true){
               console.log( "500元定金预购,得到100优惠券" );
           }else{
               order200( orderType, pay, stock );    // order500和order200耦合在一起了
           }
       }

       这依然是违反开放-封闭原则的,如果有天姚增加300元预定或者去掉200元预定,那么就意味着必须改动这些业务函数内部。

       灵活可拆分的职责链节点:


      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( "手机库存不足" );
           }
       }

 

      

       接下来把函数包装进职责链节点:
       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 === 'nestSuccessor' ){
                  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( orderNormal );

        chainOrder500.setNextSuccessor( chainOrder200 );
        chainOrder200.setNextSuccessor( orderNormal );

        chainOrder500.passRequest( 1, true, 500 ); // 输出:500元定金预购,得到100优惠券
        chainOrder500.passRequest( 2, true, 500 ); // 输出:200元定金预购,得到50优惠券
        chainOrder500.passRequest( 3, true, 500 ); // 输出:普通购买,无优惠券
        chainOrder500.passRequest( 1, false, 0 ); // 输出:手机库存不足

        现在的代码灵活多了。

 

posted @ 2016-09-01 16:17  西风.烈马  阅读(148)  评论(0编辑  收藏  举报