简介
责任链模式可以很好的帮我们处理对一个请求或者数据的阶梯级链式处理
。例如,对于一个OA审批过程
,需要从主管->部门经理->分公司经理->总经理…层层递进;或是对于某个叠加数据的层层处理,如一个Json串{A:x,B:y,C:z}
,如果A不存在就不往下判断了,对某个数据进行递进式校验(先看空不空,看长度满不满足,看字符对不对,看格式有无问题…)等等。
总之,如果需要对某项请求或者数据进行阶梯级处理
的话,推荐使用责任链模式。
传统处理
这里拿一个我之前写过的垃圾代码做例子(伪代码),就是前面所提及到的处理Json串{A:x,B:y,C:z}
。在没有了解责任链之前,我是写了一个套娃
。
// 先看json串中存不存在A
if(json.contains("A")){
if("x".equal(json.get("A"))){
// A的值等于x情况,看json串存不存在B
if(json.contains("B")){
if("y".equal(json.get("B"))){
// B的值等于y
// .....
// 后续操作
// ......
}else{
// B的值不等于y
}
}
}else{
// A的值不等于x
}
}
从上面的代码可以看出,无限套娃。本身就不便于阅读,降低了代码的可阅读性,如果项目是协同开发的话别人都不知道这代码是干嘛的;另外,如果还需要增加一个D:k
键值对,那么又需要在if里面继续添加if去判断D存在和D的值…造成代码的观赏性差,影响程序的扩展性
。
引入责任链
那么到了这里,责任链模式就可以出厂了。他可以避免上面的这种重复套娃行为,我们来看一下责任链是怎么处理的:
抽象处理类:
public abstract class AbstrctLink {
protected AbstrctLink abstrctLink;
// 定义下一个处理人
public void setAbstrctLink(AbstrctLink abstrctLink){
this.abstrctLink = abstrctLink;
}
// 处理方法交给子类实现
public abstract void handle(Map map);
}
第一关处理:
public class LinkOne extends AbstrctLink {
@Override
public void handle(Map map) {
if(map.containsKey("A") && "x".equals(map.get("A"))){
System.out.println("我处理完了A");
// 必须确保下面还有人处理
if(abstrctLink != null){
abstrctLink.handle(map);
}else{
System.out.println("链条结束");
}
}else{
System.out.println("不存在A,终止");
}
}
}
第二关处理:
public class LinkThree extends AbstrctLink {
@Override
public void handle(Map map) {
if(map.containsKey("C") && "z".equals(map.get("C"))){
System.out.println("我处理完了C");
// 必须确保下面还有人处理
if(abstrctLink != null){
abstrctLink.handle(map);
}else{
System.out.println("链条结束");
}
}else{
System.out.println("不存在C,终止");
}
}
}
第三关处理:
public class LinkTwo extends AbstrctLink {
@Override
public void handle(Map map) {
if(map.containsKey("B") && "y".equals(map.get("B"))){
System.out.println("我处理完了B");
// 必须确保下面还有人处理
if(abstrctLink != null){
abstrctLink.handle(map);
}else{
System.out.println("链条结束");
}
}else{
System.out.println("不存在B,终止");
}
}
}
主方法:
public class Main {
public static void main(String[] args) {
Map map = new HashMap();
map.put("A","x");
map.put("B","y");
map.put("C","z");
// 初始化三条链
AbstrctLink abstrctLink = new LinkOne();
AbstrctLink abstrctLink1 = new LinkTwo();
AbstrctLink abstrctLink2 = new LinkThree();
// 给三条链规定顺序
abstrctLink.setAbstrctLink(abstrctLink1);
abstrctLink1.setAbstrctLink(abstrctLink2);
// 由第一个处理即可
abstrctLink.handle(map);
}
}
完整结果:
缺少一个字段结果:
我们可以可以看到,使用了责任链模式后,代码的可读性也比较高
了;并且如果我们需要在处理新增字段的时候,只需要在增加一个链类
即可。不会影响到其它链的代码,这就比较符合了开闭原则
;并且,如果当有不匹配的情况时,也会终止责任链,直接将目前已处理的进度直接返回给调用方。
注意事项
-
需要注意的时,
链条的顺序
由客户端规定,我们对外提供一个set()方法让其注入;至于先后处理顺序由调用法自行决定。 -
如果链太长的话可以考虑使用别的方法来处理数据,如果不断创建新的链类,会造成
类爆炸
,产生许多类就不太好维护了。
小结
责任链模式在很多地方都有使用,比如servlet的Filter
,以及springmvc的请求处理链
…等等。
简单小结一下,责任链模式能为请求创建一个接收此次请求对象的链并处理
,在一定程度上提高了代码的可扩展性和可读性;但是具体怎么使用还是要结合业务情况来断定。