关于责任链模式我所知道的

简介: 关于责任链模式我所知道的

image.png


本文已参与「新人创作礼」活动,一起开启掘金创作之路。

关键词:Command ChainOfResponsibility

责任链模式在我们平时开发过程中随处可见,比如作用域链、原型链、事件冒泡等。

什么是原型链 __proto__



image.png



为什么这么设计?

JS 为了实现面向对象编程的一种设计,基于原型链可以让 JS 对象拥有封装继承多态等面向对象的特性。

什么是事件冒泡?



image.png



事件冒泡:交互事件发生后,从最小元素 div 开始传播,传到顶层 document

为什么这么设计?

最小元素上可能没有绑定 onclick 事件,所以得层层传递,传到绑定了事件函数的元素上。

换句话说:事件源本身(可能)没有处理事件的能力。


解决什么问题


上述两个例子简单介绍了下职责链模式的经典用例,类比到日常其实就像我们上学的时候上课传纸条、玩击鼓传花,纸条 谁是赵日天?,从第一排传下去,如果不是就不会应答,继续往后传递。

先来看两段珍贵无比的代码,走进职责链模式的内心世界:


业务逻辑集合递减


需求:


  1. 已生成订单,定金 500,商城优惠券 100元
  2. 已生成订单,定金 200,商城优惠券 50 元
  3. 正常购买,是否有库存,原价购买
  4. 下了单没付钱的一律按照原价购买

改造前:

/**
 * orderType: 1 -> 500定金 2 -> 200定金 3 -> 普通购买
 * isPaid -> 是否已支付定金
 * stock -> 库存
 */
function getOrder(orderType, isPaid, stock) {
  // 500元定金购买模式
  if (orderType === 1) {
    // 已支付定金       
    if (isPaid === true) {
      console.log('500元定金预购,得到100优惠券');
    } else { // 未支付定金,降级到普通购买模式   
      // 用于普通购买的手机还有库存
      if (stock > 0) {
        console.log('普通购买,无优惠券');
      } else {
        console.log('库存不足');
      }
    }
    return
  }
  // 200元定金购买模式
  if (orderType === 2) {
    if (pay === true) {
      console.log('200元定金预购, 得到50优惠券');
    } else {
      if (stock > 0) {
        console.log('普通购买, 无优惠券');
      } else {
        console.log('库存不足');
      }
    }
    return
  }
  if (orderType === 3) {
    if (stock > 0) {
      console.log('普通购买, 无优惠券');
    } else {
      console.log('库存不足');
    }
  }
}
getOrder(1, true, 500); // 500元定金预购,得到100优惠券


问题:代码冗余,大量重复的业务逻辑,难以维护。用职责链模式对代码进行改造。

改造后:

// 定义职责链上的各个节点
const orderFor500 = (orderType, isPaid, stock) => {
  if (orderType === 1 && isPaid) {
    console.log('500元定金预购 得到100优惠券')
  } else {
    return 'nextTick'
  }
}
const orderFor200 = (orderType, isPaid, stock) => {
  if (orderType === 2 && isPaid) {
    console.log('200元定金预购 得到500优惠券')
  } else {
    return 'nextTick'
  }
}
const orderForNormal = (orderType, isPaid, stock) => {
  if (stock > 0) {
    console.log('普通购买, 无优惠券')
  } else {
    console.log('库存不足')
  }
}
// 定义职责链
class Chain {
  constructor(fn) {
    this.fn = fn
    this.nextTick = null
  }
  setNextTick(nextTick) {
    return this.nextTick = nextTick
  }
  permit() {
    const res = this.fn.apply(this, arguments);
    if (res === 'nextTick') {
      return this.nextTick && this.nextTick.permit.apply(this.nextTick, arguments)
    }
    return res
  }
}


测试代码:

// 声明节点
const chainOrder500 = new Chain(orderFor500);
const chainOrder200 = new Chain(orderFor200);
const chainOrderNormal = new Chain(orderForNormal);
// 指定顺序
chainOrder500.setNextTick(chainOrder200)
chainOrder200.setNextTick(chainOrderNormal)
// 测试
chainOrder500.permit(1, true, 500)
chainOrder500.permit(2, true, 500)
chainOrder500.permit(3, true, 500)
chainOrder500.permit(1, false, 0)
// 500元定金预购 得到100优惠券
// 200元定金预购 得到500优惠券
// 普通购买, 无优惠券
// 库存不足

这样的写法也便于以后拓展,比如运营同学说:350 - 75

const orderFor350 = (orderType, isPaid, stock) => {
  // code   
}
const chainOrder350 = new Chain(orderFor350);
chainOrder500.setNextTick(chainOrder350)
chainOrder350.setNextTick(chainOrder200)


改造职责链使其能够异步


在节点函数中发起异步请求,异步请求返回的结果决定是否继续在职责链中 permit

这时候让节点函数同步返回 nextTick 就没有意义了,所以 Chain 类需要增加方法 $next,手动传递请求给职责链中的下一个节点。

// 定义职责链
class Chain {
  constructor(fn) {
    this.fn = fn
    this.nextTick = null
  }
  $next() {
    return this.nextTick && this.nextTick.permit.apply(this.nextTick, arguments);
  }
  setNextTick(nextTick) {
    return this.nextTick = nextTick
  }
  permit() {
    const res = this.fn.apply(this, arguments);
    if (res === 'nextTick') {
      return this.nextTick && this.nextTick.permit.apply(this.nextTick, arguments)
    }
    return res
  }
}
// 定义节点
const node1 = new Chain(function () {
  showResult('node-1')
  return 'nextTick'
})
const node2 = new Chain(function () {
  showResult('node-2')
  const _this = this;
  const timer = setTimeout(() => {
    _this.$next()
    clearTimeout(timer)
  }, 1000)
})
const node3 = new Chain(function () {
  showResult('node-3')
})
// 测试代码
node1.setNextTick(node2).setNextTick(node3)
node1.permit()


image.png


请求在链中的节点里传递,节点则确定什么时候把请求交给下一个节点。


定义


在 GoF 给出的定义: 在职责链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

应用场景


主要应用于解耦发起请求的对象和处理请求的对象,更好的帮助我们管理代码。针对不同场景处理请求。就比如优惠券,发帖的审核等。

参考资料:

refactoringguru 责任链模式

目录
相关文章
|
9月前
|
设计模式 Java
【设计模式】责任链模式
【设计模式】责任链模式
|
6月前
|
设计模式
|
8月前
|
设计模式 JavaScript 前端开发
如何优雅的使用责任链模式?
【6月更文挑战第7天】如何优雅的使用责任链模式?
|
9月前
|
设计模式 前端开发
【设计模式】之责任链模式
职责链模式是一种非常有用的设计模式,在前端开发中经常用于处理复杂的请求流程和数据验证。它通过将请求发送者和接收者解耦,并将请求沿着一个链条依次传递下去,实现了优雅地处理请求流程。通过使用职责链模式,我们可以提高代码的可维护性和可扩展性。然而,在应用职责链模式时需要权衡其带来的优缺点,并根据具体情况进行选择。
86 0
|
设计模式 Java
设计模式~~~责任链模式(职责链模式)
设计模式~~~责任链模式(职责链模式)
77 0
|
设计模式 C++
C++设计模式之责任链模式
好多新学设计模式的同学,对责任链模式一知半解,今天以C++为例,做个简单的分享。
103 0
|
设计模式 消息中间件 Java
一起来学设计模式之责任链模式
前言 目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本节给大家讲一下设计模式中的责任链模式,并结合实际业务场景给大家讲解如何使用~ 本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~ 责任链模式 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它能够将请求从一系列处理者中进行传递,直到有一个处理者能够处理它。这个模式将请求的发送者和接收者分离开来,使多个处理对象都有机会处理请求,将这些处理对象串成一条链,并沿着这条链传递请求,直到有一个对象能够处理请求。
责任链模式简单介绍
责任链模式简单介绍
146 0
|
Java Nacos Sentinel
责任链模式详解(上)
责任链模式详解
245 0
责任链模式详解(上)
|
设计模式 XML 数据格式