设计模式之模拟实现责任链
责任链是设计模式中很重要的一点,其思想运用到了很多框架之中,比如struct2和spring中的拦截器和过滤器。
应用场景:数据存储进数据库前,加上一系列操作来过滤数据,预防存进数据库的数据不合法。
web工程中过滤网页的请求,过滤request和response等等类似场景。
思路: 假设在一次过滤中,需要过滤多层,各层过滤不同的东西,如果一个过滤方法写一个类假设叫FilterX,那么这些类便
形成了一个链来对目标数据或代码层层过滤。如图:
那么现在就有两个个问题来考虑,过滤的方法类来怎么写?怎么才能形成一个链来依次处理?
假设一个情景,对存进数据库的一个字符串进行处理,去掉敏感词汇,将脚本语言转换,去掉首尾空格三个过滤器。
对于第一个问题,不同的过滤类有自己不同的方法,不过利用面向对象的多态性,我们可以定义一个过滤器接口,来
让各个过滤器来实现这个接口,针对上述情景,接口定义如下:
public interface MsgFilter {
String doFilter(String msg);
}
过滤器的简单实现如下:
//转换脚本语言
public class HtmlFilter implements MsgFilter{
@Override
public String doFilter(String msg) {
String r = msg.replace("<", "[").replace(">", "]");
return r;
}
}
//去掉敏感词汇(比较简单的实现)
public class SencetiveFilter implements MsgFilter{
@Override
public String doFilter(String msg) {
String r = msg.replace("敏感词汇", "");
return r;
}
}
//去掉首尾空格
public class SpaceFilter implements MsgFilter{
@Override
public String doFilter(String msg) {
String r = msg.trim();
return r;
}
}
对于第二个问题,怎样让这些过滤器呈链式工作?在这我们可以想到一个简单的方法,就是用List,来一个个遍历调用
过滤器的doFilter()方法。在这我们定义了一个MsgProcessor类来使用这个List,定义如下:
public class MsgProcessor {
private String msg;
private MsgFilter filter[] = {new HtmlFilter(), new SencetiveFilter(), new SpaceFilter()};
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String msgPro(){
String r = msg;
for(MsgFilter fil : filter){
r = fil.doFilter(r);
}
return r;
}
}
Main中来模拟调用:
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
String msg = " hello :), <script>, 敏感词汇 ";
MsgProcessor msgProcessor = new MsgProcessor();
msgProcessor.setMsg(msg);
String result = msgProcessor.msgPro();
System.out.println(result);
}
}
最后的效果输出如下:
从输出来看满足了我们的要求,链式的处理。但如果我们再想想,有了输入的处理,那输出的处理也需要同样的过滤器来处理该怎么办?
类似如下图的情况:
类似我们Javaweb的request和response,这样的过滤该怎么实现,下面我们就简单的模拟一下这个过程,request经过Filter1,2,3的过
滤后response经过Filter3,2,1的过滤处理。
类似我们也先定义一个Filter接口:
public interface Filter {
void doFilter(Request req, Response res, FilterChain chain);
}
我们再定义一个过滤链的类:
import java.util.ArrayList;
import java.util.List;
public class FilterChain implements Filter{
private List<Filter> filterChain = new ArrayList<Filter>();
private int index = -1;
public List<Filter> getFilterChain() {
return filterChain;
}
public void setFilterChain(List<Filter> filterChain) {
this.filterChain = filterChain;
}
@Override
public void doFilter(Request req, Response res, FilterChain chain) {
if(index == filterChain.size()-1)
return;
filterChain.get(++index).doFilter(req, res, chain);
}
public FilterChain addFilter(Filter filter) {
filterChain.add(filter);
return this;
}
public void removeFilter(Filter filter){
filterChain.remove(filter);
}
}