5.1-ChainOfResponsibility-职责链-行为型模式
目的
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
示例
GUI 中的组件 Tips:用户界面对象中会有一个对象来处理帮助请求,至于是哪一个对象则取决于上下文以及可用的帮助具体到何种程度。
- 问题:提交帮助请求的对象(如按钮)并不明确知道谁是最终提供帮助的对象,需要有一种办法将提交帮助请求的对象与可能提供帮助信息的对象解耦(decouple)
- 职责链:将可选的处理对象排成一条链,链中对象收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。
- 要求:每个在链上的对象都有一致的处理请求和访问链上后继者的接口
按钮、对话框和应用类都使用 HelpHandler 操作来处理帮助请求。 HelpHandler 的 HandleHelp 操作默认是将请求转发给后继。
- 要求:每个在链上的对象都有一致的处理请求和访问链上后继者的接口
适用性
- 有多个对象可以处理一个请求,哪个对象处理该请求运行时自动确定。
- 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可处理一个请求的对象集合应被动态指定。
结构

- Handler:定义处理请求的接口
- 可选:实现后继链(successor)
- ConcreteHandler:处理请求,访问后继对象
- 若能处理就处理,否则就将请求转发给后继
- Client:向职责链上的 ConcreteHandler 提交请求 当客户提交一个请求时,请求沿链传递直至有一个 ConcreteHandler 对象负责处理它。
请求传递过程可能如下

优缺点
- 降低耦合度:该模式使得一个对象无须知道是其他哪一个对象处理其请求。
- 接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构。
- 增强了给对象指派职责的灵活性:可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。
- 不保证处理:既然一个请求没有明确的接收者,那么就不能保证它一定会被处理(可能一直到链尾都没有对象处理请求)
实现
实现后继者链的方法
- 使用已有的链接:例如,在一个部分–整体层次结构中,父构件引用可定义一个部件的后继者。窗口组件(widget)结构可能早已有这样的链接。
- 由 Handler 实现:如果没有已有的引用可定义一个链,则必须构建新的链。这种情况下 Handler 不仅定义该请求的接口,通常也维护后继者

表示请求
- 请求是一个硬编码的(hard-coded)操作调用(如上述 HelpHandler)
- 使用一个处理函数,这个函数以一个请求码(如一个整型常数或一个字符串)为参数
- 无法用类型安全的方法来传递请求参数,因此它们必须被手工打包和解包。显然,相对于直接调用一个操作来说它不太安全。
解决上述参数传递问题:
- 使用独立的请求对象来封装请求参数
- Request 可定义一个访问器(accessor)函数以返回该类的标识符(对于支持的语言,可使用运行时的类型信息)
- 子类可通过重定义 HandleRequest 扩展该分派函数。子类只处理它感兴趣的请求,其他的请求被转发给父类。

相关模式
职责链常与 Composite(4.3)一起使用。这种情况下,一个构件的父构件可作为它的后继。
按钮、对话框和应用类都使用 HelpHandler 操作来处理帮助请求。 HelpHandler 的 HandleHelp 操作默认是将请求转发给后继。
