关于前端:精读设计模式-Chain-of-Responsibility-职责链模式

48次阅读

共计 2469 个字符,预计需要花费 7 分钟才能阅读完成。

Chain of Responsibility(职责链模式)

Chain of Responsibility(职责链模式)属于行为型模式。行为型模式不仅形容对象或类的模式,还形容它们之间的通信模式,比方对操作的解决应该如何传递等等。

用意:使多个对象都有机会解决申请,从而防止申请的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该申请,直到有一个对象解决它为止。

简直所有设计模式,在理解到它之前,笔者就曾经在实战中遇到过了,因而设计模式确实是从实际中得出的真知。但另一方面,如果没有实战的了解,单看设计模式是干燥的,而且难以了解的,因而大家学习设计模式时,要结合实际问题思考。

举例子

如果看不懂下面的用意介绍,没有关系,设计模式须要在日常工作里用起来,联合例子能够加深你的了解,上面我筹备了三个例子,让你领会什么场景下会用到这种设计模式。

中间件机制

构想咱们要为一个后端框架实现中间件(晓得 Koa 的同学能够了解为 Koa 的洋葱模型),在代码中能够插入任意多个中间件,每个中间件都能够对申请与响应进行解决。

因为每个中间件只响应本人感兴趣的申请,因而只有运行时才晓得这个中间件是否会解决申请,那么中间件机制应该如何设计,能力保障其性能和灵活性呢?

通用帮忙文案

如果一个大型零碎中,任何一个模块点击都会弹出帮忙文案,但并不是每个模块都有帮忙文案的,如果一个模块没有帮忙文案,则显示其父级的帮忙文案,如果再没有,就持续冒泡到整个利用,展现利用级别的兜底帮忙文案。这种零碎应该如何设计?

JS 事件冒泡机制

其实 JS 事件冒泡机制就是个典型的职责链模式,因为任何 DOM 元素都能够监听比方 onClick,不仅能够本人响应事件,还能够应用 event.stopPropagation() 阻止持续冒泡。

用意解释

JS 事件冒泡机制对前端来说太常见了,但咱们换个角度,站在点击事件的角度了解,就能从新发现其设计的精妙之处:

点击事件是叠加在每层 dom 上的,因为 dom 对事件的解决和绑定是动静的,浏览器自身不晓得哪些地方会解决点击事件,但又要让每层 dom 领有对点击事件的“平等处理权”,所以就产生了冒泡机制,与事件阻止冒泡性能。

通用帮忙文案和 JS 事件冒泡很相似,只是把点击事件换成了弹出帮忙文案罢了,其场景机理是一样的。

说到这,咱们能够再从新了解一下职责链模式的用意:

用意:使多个对象都有机会解决申请,从而防止申请的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该申请,直到有一个对象解决它为止。

申请指的是某个触发机制产生的申请,是一个通用概念。“防止申请的发送者和接收者之间的耦合关系”,指的是如果咱们只有一个对象有解决申请的机会,那接收者就与发送者之间耦合了,其余接收者必须通过这个接收者能力持续解决,这种模式不够灵便。

后半句形容的是如何设计,能够实现这个灵便的模式,行将对象连成一条链,沿着链条传递该申请,直到有一个对象解决它为止。还要了解到,任何一个对象都领有阻断申请持续传递的能力。

在中间件机制的例子中,后端 Web 框架对 Http 申请的解决就是个使用职责链模式的典型案例,因为后端框架要解决的申请是平行关系,任何申请都可能要求被响应,但对申请的解决是通过插件机制拓展的,且对每个申请的解决都是一个链条,存在解决、加工、再解决的逻辑关系。

结构图

Handler 就是对申请的解决,能够看到这里是一条环路,只有解决完之后就能够交给下一个 Handler 进行解决,能够在中途拦挡后中断,也能够穿透整条链路。

ConcreteHandler 是具体 Handler 的实现,他们都须要继承 Handler 以具备雷同的 HandleRequest 办法,这样每一个解决中间件就都领有了解决能力,使得这些对象连成的链条能够对申请进行传递。

代码例子

职责链实现形式十分多,比方 Koa 的洋葱模型实现原理就值得再写一篇文章,感兴趣的同学能够浏览 co 源码。这里仅介绍最简略场景的实现计划。

职责链的简略实现模式也分为两种,一种是每个对象自身保护到下一个对象的援用,另一种是由 Handler 保护后继者。

上面例子应用 typescript 编写。

`public class Handler {
  private nextHandler: Handler
  public handle() {
    if(nextHandler) {
      nextHandler.handle()
    }
  }
}
`

每个 Handler 的默认行为就是触发下一个链条的 handle,因而什么都不做的话,这个链条是齐全买通的,因而咱们能够在链条的任何一环进行解决。

解决的形式就是重写 handle 函数,咱们在重写时,能够维持对 nextHandler.handle() 的调用,以使得链条持续向后传递,也能够不调用,从而终止链条向后传递。

弊病

职责链模式不保障每个中间件都有机会解决申请,因为中间件程序的问题,前面中间件可能被后面的中间件阻断,因而当中间件之间存在不信赖关系时,职责链模式并不能保障中间件调用的可靠性。

另外就是不要扩充设计模式的应用范畴,对一堆对象的间断调用就没必要应用职责链模式,因为职责链适宜解决对象数量不确定、是否解决申请由每个对象灵便决定的场景,而确定了对象数量以及是否调用的场景,就没必要应用职责链模式了。

总结

职责链模式是插件机制罕用的设计模式,在事件机制、申请解决中有宽泛的利用。

职责链模式还能够与组合模式组合应用,因为组合模式形容的是一种对立治理的树形构造,每个节点都能够把本人的父节点作为后继节点。实际上 dom 构造就是一种组合模式,事件冒泡就是在其根底上拓展的职责链模式。

探讨地址是:精读《设计模式 – Chain of Responsibility(职责链模式)》· Issue #292 · dt-fe/weekly

如果你想参加探讨,请 点击这里,每周都有新的主题,周末或周一公布。前端精读 – 帮你筛选靠谱的内容。

关注 前端精读微信公众号

版权申明:自在转载 - 非商用 - 非衍生 - 放弃署名(创意共享 3.0 许可证)

正文完
 0