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

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 装饰模式
    这两个模式相似,从某个角度讲,可以相互模拟实现对方的功能。
    装饰模式是在已有的功能上增加新的功能,多个装饰器之间会有一定的联系;而职责链模式的各个职责对象实现的功能,相互之间是没有关联的,是自己实现属于自己处理的那一份功能。

参考

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 申请聚餐费用## 来考虑这样一个功能:申请聚餐费用的管理。 很多公司都有这样的福利,就是项...
    七寸知架构阅读 3,069评论 3 58
  • 原文地址:LoveDev 职责链模式(Chain of Responsibility Pattern):避免请求发...
    KevinLive阅读 319评论 0 0
  • 简介使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递...
    Mitchell阅读 272评论 0 0
  • 每次细雨 都喜欢 撑一把伞 沿青石板的小径 哒哒的行走 每当夜深 都喜欢 倚在窗前 看天空中的星星 静静的回想 以...
    海静16阅读 232评论 0 1
  • 硬是拧巴不过两岁孙子的执着,非要拽着我随全家去动物园,看那二十年没有再去过的动物园。 车上,拿着手机翻阅资料,坐落...
    倪郭阅读 865评论 4 19