本文是自己的学习笔记,主要参考以下资料
- 大话设计模式,程杰著,清华大学出版社出版
- 马士兵教育
1、责任链应用场景
想象这样一个场景,在一个论坛上发表一篇文章。文章存入数据库之前,实际上是要经过一些处理的,比如处理特殊字符,处理敏感词,格式整理,内容分析等等。
还比如,涨工资申请,第一先到主管,主管后到总监,再到总经理,最后到总裁批准。
上面的这些情况都可以抽象成,一个请求需要被多个对象处理,处理对象如链条一般排序等待处理请求。每个对象都有自己的责任。
这过程很像if else
语句
if(主管批准) {
if(总监批准) {
if(总经理批准) {
if(总裁批准) {
return "申请成功";
}
}
}
}
但这种写法非常糟糕,代码冗长不说,申请流程有变化代码也很难改变。
责任链模式就能很好解决这个问题,它将每个链结点都抽出来,每个结点只需要链接到下一个结点。当请求在该结点处理完之后便自动转到下一个结点,并且责任链结点的增加和删除都变得很容易,类似于链表结构。
2、代码详解
以论坛发表文章为例,我们建立两个Filter,一个用来处理特殊字符,一个用来处理敏感词。
2.1、建立责任链结点的抽象类
首先是先定义Filter的抽象类
interface Filter{
public boolean doFilter(Article article);
}
doFilter
方法是规范结点的处理方式,以后每个链结点的对请求的处理都是用自己的doFilter
方法。
当然,返回值不一定非得是boolean
,返回值类型为什么是这个会在后面讲解。
其中,参数Article
是对象,代表文章。
public class Article{
private String msg;
}
2.2、责任链结点的具体实现类
这是对特殊字符处理的责任结点,主要是替换<和>
防止这两个字符影响网络布局。
public class charFilter implements Filter{
@override
public boolean doFilter(Article article) {
String msg = article.getMsg();
msg.replaceAll("<", "[");
msg.replaceAll(">", "]");
article.setMsg(msg);
return true;
}
}
这个是对敏感词处理的责任结点,我们被当局要求不准出现一些字符串,必须用其他字符串替代。
public class charFilter implements Filter{
@override
public boolean doFilter(Article article) {
String msg = article.getMsg();
// remembrance the brave heart
msg.replaceAll("7846", "7856");
article.setMsg(msg);
return true;
}
}
2.3、建立链条类将结点串联起来
public class FilterChain implements Filter{
List<Filter> filters = new ArrayList();
public FilterChain add(Filter filter) {
filters.add(filter);
return this;
}
public boolean doFilter(Article article) {
for(Filter f: filters) {
if(!f.doFilter(article)) {
return false;
}
}
return true;
}
}
想将结点串起来,最简单的结构自然是ArrayList
。所以内部建立数组。
add
方法是可以在责任链上添加结点(这里我省略了remove方法)。返回类型设置为```FilterChain``是为了能链式写法添加结点,比如下面这样
filterChain.add(filter1).add(filter2);
剩下的便是doFilter
方法,该方法遍历拥有的Filter
,逐个执行他们的doFilter
方法。这里就揭晓为什么doFilter
方法要返回boolean
类型,这是为了提高效率,当某个filter
判定不通过时,那剩下的filter
也不必执行,可直接返回。比如某个filter
是审查是否文章是否血腥暴力,如果判定成功的话,那文章就直接打回。