• 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 ); // 输出:手机库存不足

            现在的代码灵活多了。

  • 相关阅读:
    python学习之【第十一篇】:Python中的文件操作
    vue2-preview引用时报错解决办法
    原生JS封装_new函数,实现new关键字的功能
    vue+element UI + axios封装文件上传及进度条组件
    Python面试题汇总
    在vue中如何使用axios
    tp5 修改默认的分页url
    jq判断是PC还是手机端的方法
    php 通过curl header传值
    windows 安装memchched和memcache教程
  • 原文地址:https://www.cnblogs.com/xbj-2016/p/5830331.html
Copyright © 2020-2023  润新知