职责链模式

95 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

导言

行为型设计模式之前学过了观察者模式、模板模式和策略模式。本篇我们再来看看职责链模式。

在GoF的《设计模式》中,它是这么定义的:

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

英文看不懂没关系,我来翻译下,大体意思是:将请求的发送和接收解耦,在其发送和接收的过程中,可以有多个对象参与其中来处理这个请求,并且这些对象串成一条链,不断的往后传递下去,直到某个对象可以处理它为止。

通过这样的描述,你可能最先会想到if-else分支结构和职责链模式何其相似是吧,每个分支就相当于发送和接收间的某个对象。这样理解其实也对,只是if-else不适合处理一些随时可能新增结构的逻辑,像职责链中的对象,可能会随时新增一个对象进来,如果还用if-else的话,很明显就破坏了开闭原则,不利于代码的维护。

购物

每年618、双十一、双十二等购物活动前,有的商家总会给出提前付定金的优惠,如预付100抵扣200,预付200抵扣500,没有预付款则按原价购买之类的。

如果不用职责链模式来编程,最常想到的恐怕就是if-else了,哈哈哈...

// 购物还需要付款金额
function price (prepay, amount) {
  let origin = 2000
  if (prepay && amount === 200) {
    return origin - 500
  } else if (prepay && amount === 100) {
    return origin - 200
  }
  return origin
}

如果仅仅是这样的简单逻辑,用if-else也没太大毛病,但如果预付款金额种类繁多且可能不同节日力度不一样,那问题就大了。我们用职责链模式来试试:

let origin = 1000
let pre200 = function (amount) {
  if (amount === 200) {
    console.log(origin - 500)
  } else {
    pre100(amount)
  }
}

let pre100 = function (amount) {
  if (amount === 100) {
    console.log(origin - amount)
  } else {
    preNormal(amount)
  }
}

let preNormal = function (amount) {
  console.log(origin - amount)
}

理解了吧,pre200,pre100和preNormal三个函数对象形成了一条链,且彼此只需要知道下一个处理对象即可,并且到能处理的对象函数即结束。完美的阐述了职责链模式的定义。当然这是最简单的应用,我们可以不断的扩展应用。