定义
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.
通过给不止一个接收者处理某个请求的机会来避免请求的发送者和接收者之间的耦合。将所有的接受者链起来,然后将请求在链上传递直到有一个接收者去处理它。
之所以首先提到这个模式,是因为我刚开始接触到的有印象的就是责任链模式。而它的用途也比较广泛,举个比较常见的例子,经常会看到一种下面这种代码:
1 | //接口列表 |
后面忽略了很大一部分的if else,这种代码不仅看起头皮发麻,而且耦合高,如果新增新的接口,必然在这个高层需要新增if else,违背了开闭原则,这时候就可以用责任链去优化,不仅灵活而且耦合度更低。
类图和代码
对于这些业务的接收者即不同接口编码的处理者,我们可以抽象出一个AbstractHandler,其中主要的有这几点:对外用于处理请求的processRequire;需要子类具体实现业务的response;子列表明自己处理的业务标志。
这里模拟一个场景:用户随时会提意见,可能是跟产品经理要求增加功能;可能是要求程序员优化代码,可能是要求UI修改一下图片样式等。
类图如下:
抽象处理父类代码如下:
1 | public abstract class AbstractHandler { |
用户提需求的一个抽象:
1 | public interface IRequirement { |
然后分别定义几个部门里的技术支持人员:
1 | /** |
其他如产品经理或者UI设计师也类似。
然后模拟用户可能会提的需求种类:
1 | /** |
其他UI需求,或者产品需求也同上类似。
再建立一个映射类,每次调用只需要在映射类里找到责任链第一个节点,并组装链返回即可:
1 | class MappingHandler{ |
在高层的控制层就可以很轻松地调用了,它不需要知道是谁处理的和处理细节,传入参数就能拿到返回值:
1 | /** |
打印结果:
程序员拿到需求为:优化一下代码!!!,正在处理!
产品经理获得需求为:增加一个功能!!!,正在处理中
无法处理该请求:未知请求
借助Spring
借助于Spring,我们还可以玩出更炫酷的花样。我们都知道链节点的增多会导致每个请求不同的递归调用、判断会耗费很多的判断时间,但是如果此时假如能有个容器,通过循环容器里的AbstractHandler找到每个子类的处理等级,将处理等级同请求类型比对,成功即可具体操作业务,这样效率会高很多,这时候Spring 的酷炫玩法就来了:
AbstractHandler的代码基本保持一致,但是setNextHandler这个方法就可以不用了,需要新增一个getRequireType来作为模板方法获取当前子类的处理类型:
1 | public abstract class AbstractHandler { |
将所有子类纳入Spring容器的管理,加上注解即可:
1 |
|
Product和Ui两个类同理。
1 |
|
测试类:
1 | (SpringRunner.class) |
执行结果:
程序员拿到需求为:优化一下代码!!!,正在处理!
产品经理获得需求为:增加一个功能!!!,正在处理中
总结
优点:将请求和处理分开,甚至不需要处理细节;扩展方便,以后新增业务只需要新增一个业务类型,接入链即可,结合spring甚至只需要新增业务类,耦合度大大降低;
缺点:链如果太长会导致性能问题;链太长不利于调试。