Chain of ressponsibility 模式——推卸责任
1、什么是推卸责任?
将多个对象组成一条职责链,然后按照它们在职责链上的顺序来逐个找出到底应该谁来负责。
1、Chain of ressponsibility 模式的重要性
弱化“请求方”和“处理方”之间的关联关系,让双方各自都成为可独立复用的组件。
程序可对付其他需求,如根据情况不同,负责处理的对象也会发生变化的这种需求。
2、示例程序
示例程序类
Trouble 表示发生的问题的类。它带有问题的编号(number)
Support用来解决问题的抽象类
NoSupport用来解决问题的具体类(永远不处理问题)
LimitSupport用来解决问题的具体(仅解决编号小于指定编号的问题)
OddSupport用来解决问题的具体(仅解决奇数编号问题)
SpecialSupport用来解决问题的具体(仅解决指定编号的问题)
Main制作Support职责链,制造问题并测试程序行为。
示例程序类图
Trouble类
Support类
NoSupport类
LimitSupport类
OddSupport类
SpecialSupport类
Main类
运行结果
解决Trouble363时的示例程序的时序图
下图展示了各个责任链在调用下一个Support方法之前都会先调用自身的resolve方法。
3、chain of responsibility 模式中的登场角色
Handler(处理者)
Handler角色定义了处理请求的接口(API)。Handler角色知道“下一个处理者”是谁,如果自己无法处理请求,他会将请求转给“下一个处理者”。当然,“下一个处理者”
ConcreteHandler(具体的处理者)
Client(请求者)
拓展思路的要点
弱化了发出请求的人和处理请求之间的关系
Chain of responsibiliy模式最大的优点在于弱化了发出请求的人(Client角色)和处理请求的人(ConcreteHandler)之间的关系。Client角色向第一个ConcreteHandler角色发出请求,然后会在职责链中传播,直到某个ConcreteHandler角色处理该请求。
既然知道Chain of responsibiliy模式这么伟大,那么,如果它不存在,那么我们该如何处理请求呢?
很明显,如果不采用推卸责任的方式去处理请求,那么我们就必须有这样一个伟大的角色知道“谁应该处理什么请求”。显然,让“发出请求的人”知道“谁应该处理该请求”,会降低其作为可复用组件的独立性。
可以动态地改变职责链
在前面的示例程序中,问题解决的次序如下:
但是假设上面的6个角色中的某些角色之间的关系可能会发生变化,如果委托推卸责任,就能根据情况变化动态地重组职责链。
假设不使用责任链模式,而是在程序中下达死命令“某个程序需要谁处理”这样的对应关系,那么很难再程序运行中去改变请求的处理者。
一个很实在的栗子:chain of responsibility 模式在视窗系统中的发挥了很大的作用。
专注于自己的工作
ConcreteHandler勇敢地说不,才能让它专注于自己的工作,假如我们不使用责任链模式,首先得有一个“选举哪个ConcreteHandler该负责什么样处理”的方法。或者是每个ConcreteHandler自己负责“任务分配工作”,即“自己不能处理的转交给别人”。
推卸请求会导致处理延迟吗?
回答是肯定的,接受到请求之后并不能立马去处理请求,所以会导致延迟。如果说责任和处理者之间的关系是明确的,那么我们应该放弃Chain of responsibiliy模式。
相关的设计模式
Composite 模式
Handler角色会经常使用Composite 模式
Command 模式
有时会使用Command模式向Handler角色发送请求。
jfinal的 Chain of responsibility模式
首先通过Main方法启动项目,发送请求给doFilter完成项目的真正启动,在这里实现handler的初始化还有调用责任链,handler通过HandlerFactory定义了责任链规则。在这里实现Handler有两种方式:
1)自定义handler,如类图中的DemoHandler;
2)调用Jfinal中handler;
jfinal框架中有ContextPathHandler、FakeStaticHandler、ServerNameRedirect301Handler、ActionHandler,这些ConcreteHandler通过集成Handler,实现Handler中抽象Handle方法,完成责任的细分。
原文地址:https://www.cnblogs.com/Erma/p/10330766.html