学而时习之,温故而知新。这句话用在设计模式上真是太恰当不过了!博主从上大二的时候就开始阅读设计模式,当时对面向对象的思维理解的不是很深刻。所以一些设计模式弄得一知半解,只知其形而不知其神。工作之余也没有放弃过对设计模式的学习和琢磨,每次阅读相关的设计模式总有不同的心得体会。收货颇多。所以在此建议读者也要时不时翻看下设计模式。从中演化出适合自己的模式出来。可以说设计模式是面向对象思维的集大成者。越阅读越有味道。
闲言少叙,本篇博文就简单的梳理下博主对责任链模式的理解和体会,如有不当之处欢迎批评指正。正规的责任链模式有如下两点:
1、责任链一般有两种对象,一个是请求者。一个是处理者。需要注意的是<font color="#ff00ff">处理者是有可能返回处理结果给请求者的</font>。查阅了好多篇关于责任链模式的文章,这点好像都没有提及。
2、多个对象中,每个对象都持有下一个对象的引用,这就构成了链这种结构。(但是一定要如此吗?后面会有说明)
因为在代码设计中我们会将处理者抽象出一个接口,所以实现这个接口的处理者可能。
在这里插入图片描述
责任链模式的主要工作就是在众多的处理者中找到能处理当前请求的那一个处理者对象!所以具体的处理者需要持有下一个处理者的引用!ConcreteHandler1
伪代码如下:
public class ConcreteHandler1 extends Handler{
protected Handler nextHandler;//下一个处理者
@Override
public void handleRequest() {
if ( 符合处理要求) {
//进行处理 逻辑
doMyJob();
} else {//不符合则交给下一个处理者
nextHandler.handleRequest();
}
}
}
责任链模式的一个特点就是<font color="#ff00ff">当前处理者必须知道下一个处理者是谁</font>。初始化当前处理者的时候也要把下一个处理者进行绑定。其实如果当前处理者不需要知道下一个处理者是谁的话,完全可以这么调用:
List<Handler> handlers=initHandlers();
for(Handler currentHandler:handlers){
if(currentHandler.isHandlebale()){//如果当前能够处理当前请求
currentHandler.handleRequest();
break;//处理完毕,跳出循环
}
}
上面这个for循环的责任链模式甚至可以说是ConcreteHandler1
代码的扩展,因为它比较灵活!ConcreteHandler1
在设计的时候需要指定下一个处理者。而for循环遍历的这种方式,我们只需要在initHandlers()
初始化处理者集合的时候,合理的安排好集合中的顺序即可将这种击鼓传花的游戏玩下去。
考虑到另外一个场景:公司的请假系统,需要层层批准,上一个部分批准后需要把后续流程交个下一个部门,这种工作模式最适合责任链模式。但是如果需要层层批准的话,那么上面的伪代码ConcreteHandler1
就不符合,因为它处理完属于自己的工作后就不忘后传了,所以就需要进行如下改造:
public class ConcreteHandler1 extends Handler{
protected Handler nextHandler;//下一个处理者
@Override
public void handleRequest() {
//处理属于我自己分内的逻辑
doMyJob();
//处理完成后,后续流程交给下一个处理者
nextHandler.handleRequest();
}
}
在平时写代码中,其实自己很少用过这种设计模式。但是有一个框架把这个模式用的很出彩,那就是Okhttp框架。其拦截器的设计理念堪称责任链模式的灵活使用的典范,关于Okhttp框架的分析可参考博主的专栏okhttp源码解析。
在OKhttp的拦截器中,发起一个网络请求,我们将请求封装成Request对象。交给拦截器中的某个拦截器,该拦截器处理完自己的工作之后,根据具体业务逻辑判断是否需要交给下一个拦截器。如果不需要,就将处理结果Response对象返回给请求者!其流程图如下图所示:
在这里插入图片描述
到此为止,关于责任链模式的心得体会书写完毕。后期可能随着自己体会的不断加深,该篇博文需要进行修改,敬请期待吧。
网友评论