温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Chain of Responsibility职责链模式怎么实现

发布时间:2022-03-25 10:49:03 来源:亿速云 阅读:165 作者:iii 栏目:web开发

本文小编为大家详细介绍“Chain of Responsibility职责链模式怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Chain of Responsibility职责链模式怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

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() 的调用,以使得链条继续向后传递,也可以不调用,从而终止链条向后传递。

弊端

职责链模式不保证每个中间件都有机会处理请求,因为中间件顺序的问题,后面中间件可能被前面的中间件阻断,因此当中间件之间存在不信任关系时,职责链模式并不能保证中间件调用的可靠性。

另外就是不要扩大设计模式的使用范围,对一堆对象的连续调用就没必要使用职责链模式,因为职责链适合处理对象数量不确定、是否处理请求由每个对象灵活决定的场景,而确定了对象数量以及是否调用的场景,就没必要使用职责链模式了。

读到这里,这篇“Chain of Responsibility职责链模式怎么实现”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI