《js 设计模式与开发实践》读书笔记 13

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

  这个在我们项目中,这种模式的最大优点是,请求发送者只需要知道链中的第一个节点,从而弱化了发送者和一组接收者之间的强联系。假设我们负责一个售卖手机的网站,经过分别交纳 500 元定金和 200 元定金两轮预定后,现在已经到了正式购买的阶段。公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用户会收到 100 元的商城券,200 元定金的用户可以收到 50 元的优惠券,而之间的没有支付过定金的只能进入普通购买模式,且在库存有限的情况下不一定保证能买到。

  我们的订单页面是 php 吐出的模板,在页面加载之初,php 会传递给页面几个字段。orderType,表示订单类型,code 1,500 元定金用户,2 时 200 元定金用户,3 是普通用户。pay:表示用户是否已经支付定金,值为 true 或 false,下个定金的订单,没支付就是 false,stock:表示当前用于普通购买的手机库存数量,已经支付过 500 或 200 定金的不受此限制。

var order = function (orderType, pay, stock) {
  if (orderType === 1) {
    if (pay) {
      console.log('500定金预购,得到100优惠券')
    } else {
      if (stock > 0) {
        console.log('普通购买,无优惠券')
      } else {
        console.log('手机库存不足')
      }
    }
  } else if (orderType === 2) {
    if (pay) {
      console.log('200定金预购,得到50优惠券')
    } else {
      if (stock > 0) {
        console.log('普通购买,无优惠券')
      } else {
        console.log('手机库存不足')
      }
    }
  } else {
    if (stock > 0) {
      console.log('普通购买,无优惠券')
    } else {
      console.log('手机库存不足')
    }
  }
}

order(1, true, 500)

  虽然我们得到了意料之中的运行结果,但这远远算不上一段值得夸奖的代码。order 函数不仅巨大而且难以阅读,还可能经常修改,虽然现在能运行,但接下来维护是一个噩梦。有很多重构方式,我们先用职责链来重构代码。

var order500 = function (orderType, pay, stock) {
  if (orderType === 1 && pay === true) {
    console.log('500定金,100优惠券')
  } else {
    order200(orderType, pay, stock)
  }
}

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)
order500(2, false, 0)

  可以看到,执行结果和前面那个巨大的 order 函数完全一样,但是代码结构已经清晰了很多,我们把一个大函数拆分成了 3 个小函数。去掉了许多嵌套的条件分支语句。但是我们不满足于此,虽然已经把大函数拆分成了互不影响的 3 个小函数,但是,请求在链条传递中的顺序很僵硬,传递请求的代码被耦合在了业务函数之中。如果有天我们要增加 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 === '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(orderNormal)

chainOrder500.setNextSuccessor(chainOrder200)
chainOrder200.setNextSuccessor(chainOrderNormal)

chainOrder500.passRequest(1, false, 0)

  以后想支持300.我们把500的下一个改好。他的下一个节点改成200就可以了。虽然这写起来可优点难受。在开发中,只要运用得当,职责链模式可以很好的帮助我们管理代码,降低发起请求的对象和处理请求对象之间的耦合性。职责链中的节点数量和顺序是可以自由变化的。dom的时间冒泡和原型链实现中都有职责链的影子。

posted @ 2022-09-19 10:43  艾路  阅读(19)  评论(0编辑  收藏  举报