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

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函数之匿名函数

各位小伙伴,周五快乐! 今天是2017年最后一个工作日,大家都在忙碌些什么呢? 今天我们要讲的是Python函数中的匿名函数 好像函数中的分类及说法很多,但是大...

1936
来自专栏xingoo, 一个梦想做发明家的程序员

JS面向对象高级特性

本篇是通过学习视频《一头扎进javascirpt高级篇》整理的一些相关知识,大致包括下面几个方面:   1 对象的创建方法   2 对象的对象属性、私有属...

20110
来自专栏别先生

jdk1.8学习、jdk1.9学习、jdk10.0学习和总结

https://www.oschina.net/translate/109-new-features-in-jdk-10

441
来自专栏青枫的专栏

java基础学习_面向对象(下)02_day09总结

============================================================================= ==...

502
来自专栏游戏开发那些事

【Unity游戏开发】浅谈Lua和C#中的闭包

  目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#。通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑。这...

1362
来自专栏技术博文

php设计模式

什么是设计模式 设计模式,是一种解决问题的思维,而并非某种特定的方法。是前人给我们总结的宝贵经验。学习设计模式是为了编写可复用、可拓展、高性能软件。学习设计模式...

2789
来自专栏大闲人柴毛毛

三句话搞定适配器模式

适配器模式的官方定义: 将一个与当前类无法兼容的接口转换成能够兼容当前类的接口。 适配器模式的大白话: 现在有一个第三方类/我们项目组中别人写的类放在我们面前,...

3286
来自专栏JMCui

浅析Java RTTI 和 反射的概念

一、概念: RTTI(Run-Time Type Identification,运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象...

3827
来自专栏Java帮帮-微信公众号-技术文章全总结

【Java提高四】接口与抽象类

【Java提高四】接口与抽象类 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法。 抽象类与接口是java语言中对抽象概念进行定义的...

3386
来自专栏Java Web

Java 8——Lambda表达式

本文内容大部分来自《Java 8实战》一书 前言 在上一篇文章中,我们了解了利用行为参数化来传递代码有助于应对不断变化的需求,它允许你定义一个代码块来表示一个...

3133

扫码关注云+社区