设计模式 ——— 职责链模式

CHAIN OF RESPONSIBILITY(职责链) ———— 对象行为型模式

意图

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

适用性

  • 如果有多个对象可以处理同一个请求,但是具体由哪个对象来处理该请求,是运行时刻动态确定的。这种情况可以使用职责链模式,把处理请求的对象实现成为职责对象,然后把它们构成一个职责链,当请求在这个链中传递的时候,具体由哪个职责对象来处理,会在运行时动态判断。
  • 如果你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求的话,可以使用职责链模式,职责链模式实现了请求者和接收者之间的解耦,请求者不需要知道究竟是哪一个接收者对象来处理了请求。
  • 如果想要动态指定处理一个请求的对象集合,可以使用职责链模式,职责链模式能动态的构建职责链,也就是动态的来决定到底哪些职责对象来参与到处理请求中来,相当于是动态指定了处理一个请求的职责对象集合。

结构

  • Handler(职责接口) 通常在这里定义处理请求的方法,可以在这里实现后继链。
  • ConcreteHandler(具体职责类) 在这个类里面,实现对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者。
  • Client(职责链的客户端) 向链上的具体处理者对象提交请求,让职责链负责处理。

对职责链模式实现的深入探讨

  • 实现后继者链 ① 定义新的链接;② 使用已有的链接 当已有的链接能够支持你所需的链时,完全可以使用它们。这样你不需要明确定义链接,而且可以节省空间。但如果该结构不能反映应用所需的职责链,那么你必须定义额外的链接。 比如,当前职责处理对象引用了一个"职责链_One”作为它的后继者链,而这个"职责链_One”中已经存在了它自己的后继者链,假设这个"职责链_One”完整的链为“A ——> B ——> C”。这样当前的职责处理对象其实并没有明确的指定“A ——> B ——> C”这个链,而是通过组合的模式复用了该链。
  • 隐式接收者 当客户端发出请求的时候,客户端并不知道谁会真正处理他的请求,客户端只知道他提交请求的第一个对象。从第一个处理对象开始,整个职责链里面的对象,要么自己处理请求,要么继续转发给下一个接收者。 也就是对于请求者而言,并不知道最终的接收者是谁,但是一般情况下,总是会有一个对象来处理的,因此称为隐式接收者。
  • 一个职责链处理多种请求 ① 在Handler中定义不同的方法表示不同的请求。这种形式方便而且安全,但你只能转发Handler类定义的固定的一组请求。 ② 定义一个请求对象类(Request)来封装请求的类型和参数。Handler中依旧指定义一个通用的请求方法,该方法不区分请求的类型,所以的请求都是调用该方法,具体的请求类型通过请求对象(Request)中的请求类型属性来标识。那么在具体的接收者中就可以通过Request中标识的不同请求类型进行不同的逻辑处理,处理逻辑依旧是要么处理该请求,要么将该Request对象传递给下一个接收者。
  • 连接后继者 可以在Handler中定义一个请求的缺省实现,即,将请求传递给后继者(如果有后继者的话)。这样一来如果ConcreteHandler子类对该请求不感兴趣,则不需要重定义请求处理操作,因为它的缺省实现会进行无条件的转发。

优缺点

优点: ① 降低耦合度 在职责链模式里面,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发出请求就可以了。接收者和请求者都没有对象的明确的信息,且链中的对象不需要知道链的结构。 结果是,职责链可简化接收者对象的相互连接。它们仅需保持一个指向其后续者的引用,而不需要保持它所有的候选接收者的引用。 ② 增强了给对象指派职责的灵活性 当在接收者中分派职责时,职责链给你更多的灵活性。你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。

缺点: ① 不保证被接受 既然一个请求没有明确的接收者,那么就不能保证它一定会被处理 ———— 该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有正确配置而得不到处理。

功能链

在实际开发中,经常会出现一个把职责链稍稍变形的用法。在标准的职责链中,一个请求在职责链中传递,只要有一个对象处理了这个请求,就会停止。 现在稍稍变一下,改成一个请求在职责链中传递,每个职责对象负责处理请求的某一方面的功能,处理完成后,不是停止,而是继续向下传递请求,当请求通过很多职责对象处理过后,功能也就处理完了,把这样的职责链称为功能链。

相关模式

  • 职责链模式 VS 组合模式 这两个模式可以组合使用。 可以把职责对象通过组合模式来组合,这样可以通过组合对象自动递归的向上调用,由父组件作为子组件的后继,从而形成链。
  • 职责链模式 VS 装饰模式 这两个模式相似,从某个角度讲,可以相互模拟实现对方的功能。 装饰模式是在已有的功能上增加新的功能,多个装饰器之间会有一定的联系;而职责链模式的各个职责对象实现的功能,相互之间是没有关联的,是自己实现属于自己处理的那一份功能。
参考

《设计模式:可复用面向对象软件的基础》 《研磨设计模式》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏武军超python专栏

2018年8月25日多线程编程总结

PYTHON 本身也支持多任务处理,并且提供了如下的操作方式 多线程多任务处理机制   (比较常用) 多进程多任务处理机制   (不常用,大型项目开发或者系...

984
来自专栏我是攻城师

Nodejs笔记(三)

3379
来自专栏开源优测

接口测试 | 25 requests + pytest测试实例

概述 本文主要分享如何将pytest和requests结合一起使用,让大家有个初步的了解。 主要内容有: pytest简介 pytest + requests示...

5679
来自专栏乐享123

How to Parallel All Cmds for Linux

1434
来自专栏Python绿色通道

Python的进程

Python实现多进程的方式主要有两种:一种方法是使用os模块中的fork方法; 另一种是使用multiprocessing模块。这两种方法的区别在于前者仅适用...

802
来自专栏老九学堂

Java微课堂之基本选择结构2

本节讲解知识点回顾 ? ? ? 本节编程技巧和注意事项 条件选择结构关于分号和大括号什么时候可以打,什么时候不用打,它的意义是不同的。

2716
来自专栏小筱月

shell 文本操作命令

:s/old/new/g 将当前行中查找到的所有字符串“old” 替换为“new”

972
来自专栏C/C++基础

Linux命令(31)——find命令

find命令用于在指定目录查找文件,可以指定一些匹配条件,如按文件名、文件类型、用户甚至是时间戳来查找文件。

1094
来自专栏大眼瞪小眼

介绍PHP的自动加载

include 和 require 是PHP中引入文件的两个基本方法,但是每个脚本的开头,都需要包含(include)一个长长的列表总是不好的,所以 PHP 使...

1052
来自专栏python百例

29-文件对象基础操作

822

扫码关注云+社区