一天一种设计模式---职责链模式

135 阅读2分钟

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

  1. 场景

    商场优惠券, 预交500 得 100, 预交 300 得 50, 提前付钱就一定有货, 没付自动为普通用户,并且可能会由于没有库存不给发货。

    function order(orderType, pay, stock) {
         if (orderType == 1) {
             if (pay) {
                 console.log('获得100优惠券')
             } else {
                 console.log('变成普通用户')
                 if (!stock) {
                     console.log('没有库存了')
                 }
             }
         }
         if (orderType == 2) {
             if (pay) {
                 console.log('获得50优惠券')
             } else {
                 console.log('变成普通用户')
                 if (!stock) {
                     console.log('没有库存了')
                 }
             }
         }
         if (orderType == 3) {
             console.log('普通用户')
             if (!stock) {
                 console.log('没有库存了')
             }
         }
     }
     order(2, true, 0);  //结果:  获得50优惠券
    
    

    上述写法代码冗余太多,if判断太多。

function doOne(orderType, pay, stock) {
      if (pay && orderType == 1) {
          console.log('500优惠')
      } else {
          doTwo(orderType,pay, stock)
      }
  }

  function doTwo(orderType, pay, stock) {
      if (pay && orderType == 2) {
          console.log('300优惠')
      } else {
          doThree(orderType,pay, stock)
      }
  }
  function doThree(orderType, pay, stock) {
      if (orderType == 3)
          console.log('普通用户')
      if (!stock) {
          console.log('没有库存了')
      }
  }



  doOne(2, true, 0);

优点: 减少了很多if,但依然违背开放-封闭原则。

改,面向对象:

var orderNum = function (fn) {
      this.fn = fn;
      this.next = null;
  }

  orderNum.prototype.nextFun = function (next) {
      return this.next = next;
  }

  orderNum.prototype.todoNext = function () {
      let res = this.fn.apply(this, arguments);
      if (res === 'noSuccess') {
          return this.next && this.next.todoNext.apply(this.next, arguments)
      }
  }

  function onOne(type, pay, stock) {
      if (type == 1 && pay) {
          console.log('获得100优惠')
      } else {
          return 'noSuccess'
      }
  }

  function onTwo(type, pay, stock) {
      if (type == 2 && pay) {
          console.log('获得50优惠')
      } else {
          return 'noSuccess'
      }
  }

  function onThree(type, pay, stock) {
      console.log('普通用户')
      if (!stock) {
          console.log('没有库存')
      }
  }
  
  var one = new orderNum(onOne);
  var two = new orderNum(onTwo);
  var three = new orderNum(onThree);
  
  one.nextFun(two);
  
  two.nextFun(three)
  
  one.todoNext(1,true,500)  //获得100优惠
  one.todoNext(2,true,500)  //获得50优惠
  one.todoNext(3,true,500)  //普通用户

上述例子,优点: 易扩展,不用修改原来代码结构。 缺点: 太重。

  1. 改成异步
var orderNum = function (fn) {
     this.fn = fn;
     this.next = null;
 }

 orderNum.prototype.nextFun = function (next) {
     return this.next = next;
 }

 orderNum.prototype.todoNext = function () {
     let res = this.fn.apply(this, arguments);
     if (res === 'noSuccess') {
         return this.next && this.next.todoNext.apply(this.next, arguments)
     }
 }

 orderNum.prototype.nextTo = function () {   //新增手动执行下一步方法
     return this.next && this.next.todoNext.apply(this.next, arguments)
 }

 function onOne(type, pay, stock) {

     if (type == 1 && pay) {
         console.log('获得100优惠')
     } else {
         setTimeout(() => {
             this.nextTo(type,pay,stock)      //手动控制下一步
         }, 2000)
         // return 'noSuccess'
     }
 }

 function onTwo(type, pay, stock) {
     if (type == 2 && pay) {
         console.log('获得50优惠')
     } else {
         return 'noSuccess'
     }
 }

 function onThree(type, pay, stock) {
     console.log('普通用户')
     if (!stock) {
         console.log('没有库存')
     }
 }
 var one = new orderNum(onOne);

 var two = new orderNum(onTwo);

 var three = new orderNum(onThree);

 one.nextFun(two).nextFun(three)

 one.todoNext(2, false, 500)  

3.aop写法

  function onOne(type, pay, stock) {
        if (type == 1 && pay) {
            console.log('获得100优惠')
        } else {
            return 'noSuccess'
        }
    }

    function onTwo(type, pay, stock) {
        if (type == 2 && pay) {
            console.log('获得50优惠')
        } else {
            return 'noSuccess'
        }
    }

    function onThree(type, pay, stock) {
        console.log('普通用户')
        if (!stock) {
            console.log('没有库存')
        }
    }

    Function.prototype.before = function (before) {
        var _self = this;
        return function () {
            before.apply(this, arguments);
            return _self.apply(this, arguments)
        }
    }
    
    Function.prototype.after = function (after) {
        var _self = this;
        return function () {
            var res = _self.apply(this, arguments);
            if (res == 'noSuccess')
                return after.apply(this, arguments);
        }
    }

    var order = onOne.after(onTwo).after(onThree);

    order(1,true,200)    //获得100优惠