设计模式之责任链模式

如果要对这样的字符串“大家好:),<script>,敏感,设计模式,责任链模式”进行过滤,把其中的“:)、<、>、敏感”等字眼过滤掉,那么可以定义一个接口,实现了此接口的类可以对要过滤的字符串进行过滤,接口如下:

public interface Filter {

	public String doFilter(String string);
}

实现此接口用于过滤“:)”的类如下:

public class FaceFilter implements Filter {

	@Override
	public String doFilter(String string) {
		return string.replace(":)", "^V^");
	}

}

用于过滤“<、>”的类如下:

public class HTMLFilter implements Filter {

	@Override
	public String doFilter(String string) {
		return string.replace("<", "[").replaceAll(">", "]");
	}

}

用于过滤“敏感”等敏感字眼儿的类如下:

public class SensitiveFilter implements Filter {

	@Override
	public String doFilter(String string) {
		return string.replace("敏感", "***");
	}

}

再定义一个专门用来进行过滤的处理类如下:

public class MsgProcessor {
	
	private String msg;
	private Filter[] filters;
	
	public MsgProcessor(String msg, Filter[] filters) {
		this.msg = msg;
		this.filters = filters;
	}
	
	public String process() {
		for(Filter filter : this.filters) {
			this.msg = filter.doFilter(this.msg);
		}
		return this.msg;
	}

}

只要传入要过滤的字符串和过滤器就可以实现过滤的效果,如下:

public class Client {

	public static void main(String[] args) {
		String msg = "大家好:),<script>,敏感,设计模式,责任链模式";
		
		Filter[] filters = new Filter[]{new HTMLFilter(), new SensitiveFilter(), new FaceFilter()};
		MsgProcessor processor = new MsgProcessor(msg, filters);
		
		String result = processor.process();
		System.out.println(result);
	}

}

最后,输出结果为“大家好^V^,[script],***,设计模式,责任链模式”,即实现了过滤的功能,当然,要真正地实现过滤可不会这么简单,这里只是起到简单的说明作用。

可以发现这里的三个过滤类类似处于一条链条上,有顺序,挨个执行过滤功能,多个过滤器用在一起就形成了过滤器链,如下图所示:

既然多个过滤器用在一起就形成了过滤器链条,那么可以换种方式更直观的体现“链”这个概念,新建一个类叫做"FilterChain"如下:

public class FilterChain {
	
	private List<Filter> filterList = new ArrayList<Filter>();
	
	public FilterChain addFilter(Filter filter) {
		this.filterList.add(filter);
		return this;
	}
	
	public String doFilter(String msg) {
		String result = msg;
		for(Filter filter : this.filterList) {
			result = filter.doFilter(result);
		}
		return result;
	}

}

把多个过滤器先装在一个List中,再做处理,是不是更能体现“链”这个概念了呢?接着,修改上面的MsgProcessor类,如下:

public class MsgProcessor {
	
	private String msg;
	private FilterChain chain;
	
	public MsgProcessor(String msg, FilterChain chain) {
		this.msg = msg;
		this.chain = chain;
	}
	
	public String process() {
		return this.chain.doFilter(this.msg);
	}

}

最后是客户端调用,如下:

public class Client {

	public static void main(String[] args) {
		String msg = "大家好:),<script>,敏感,设计模式,责任链模式";
		
		FilterChain chain = new FilterChain();
		chain.addFilter(new HTMLFilter())
			 .addFilter(new SensitiveFilter())
			 .addFilter(new FaceFilter());
		MsgProcessor processor = new MsgProcessor(msg, chain);
		
		String result = processor.process();
		System.out.println(result);
	}

}

一样起到了过滤的效果,注意观察FilterChain类中有一个与Filter接口中定义的方法同名的doFilter方法,这并不是偶然,这是有好处的,FilterChain中的处理方法也叫做doFilter是因为当FilterChain类也实现了Filter方法时,不用更改方法名,就能实现往已经存在的过滤器链中加入新的过滤器链,形成一个新的过滤器链,如下图,让FilterChain类实现Filter接口:

/**
 * 让FilterChain类也实现Filter接口,不仅能往过滤器链条中加入新的过滤器,
 * 还能实现往已存在的过滤器链中加入新的过滤器链条
 * @author Administrator
 *
 */
public class FilterChain implements Filter{
	
	private List<Filter> filterList = new ArrayList<Filter>();
	
	public FilterChain addFilter(Filter filter) {
		this.filterList.add(filter);
		return this;
	}
	
	@Override
	public String doFilter(String msg) {
		String result = msg;
		for(Filter filter : this.filterList) {
			result = filter.doFilter(result);
		}
		return result;
	}

}

客户端在已存在的过滤器链中加入新的过滤器链:

public class Client {

	public static void main(String[] args) {
		String msg = "大家好:),<script>,敏感,设计模式,责任链模式";
		
		FilterChain chain01 = new FilterChain();  //过滤器链01
		chain01.addFilter(new HTMLFilter())
			 .addFilter(new SensitiveFilter());
		
		FilterChain chain02 = new FilterChain();  //过滤器链02
		chain02.addFilter(new FaceFilter());
		 
		chain01.addFilter(chain02);   //往过滤器链01中加入过滤器链02形成新的过滤器链
		
		MsgProcessor processor = new MsgProcessor(msg, chain01);
		
		String result = processor.process();
		System.out.println(result);
	}

}

以上的过程中实现的都是单向的过滤,如果要模拟“客户端对服务器端的请求”和“服务器端处理客户端请求并返回”,在请求和返回的过程中都进行过滤,又该怎么办呢?新建两个类Request和Response,用于模拟请求对象和返回对象,如下:

Request类:

public class Request {

	private String requestMsg;
	
	public String getRequestMsg() {
		return requestMsg;
	}

	public void setRequestMsg(String requestMsg) {
		this.requestMsg = requestMsg;
	}

	public Request(String requestMsg) {
		this.requestMsg = requestMsg;
	}
	
}

Response类:

public class Response {

	private String responseMsg;
	
	public String getResponseMsg() {
		return responseMsg;
	}

	public void setResponseMsg(String responseMsg) {
		this.responseMsg = responseMsg;
	}

	public Response(String responseMsg) {
		this.responseMsg = responseMsg;
	}
	
}

注意:这里要实现的并不是对请求和返回进行同时过滤,而是当对请求过滤完毕后再对返回进行过滤,且过滤执行的顺序的相反的,如下图:

既然是实现对请求过滤完毕后再对返回进行过滤,那么在执行一个过滤器完毕后应该继续调用下一个过滤器继续对请求进行过滤,而不能当一个过滤器对请求过滤完毕后马上执行对返回的过滤,所以上一个过滤器应该知道下一个过滤器;而且现在处理的是双向的过滤,而不是之前单向的过滤,所以应该修改Filter接口,如下:

public interface Filter {

	public void doFilter(Request request, Response response, FilterChain chain);
}

当然,之前实现此接口的过滤器也要修改,首先是FilterChain类,现在这个类的功能是判断到底还有没有下一个过滤器,如果有取出来并执行它就实现了过滤器调用下一个过滤器,如果没有了,那么说明执行到了过滤器链的最后,说明对一个方向的过滤已过滤完毕,那么应该对另一个方向进行过滤了,所以返回,将控制权交给调用它的那个过滤器,执行对另一个方向的过滤开始,如下:

/**
 * 让FilterChain类也实现Filter接口,不仅能往过滤器链条中加入新的过滤器,
 * 还能实现往已存在的过滤器链中加入新的过滤器链条
 * @author Administrator
 *
 */
public class FilterChain implements Filter{
	/**
	 * 用于判断下一个过滤器
	 */
	private int index;
	private List<Filter> filterList = new ArrayList<Filter>();
	
	public FilterChain addFilter(Filter filter) {
		this.filterList.add(filter);
		return this;
	}
	
	@Override
	public void doFilter(Request request, Response response, FilterChain chain) {
		if(this.index == this.filterList.size()) {
			return;
		}
		Filter filter = this.filterList.get(this.index++);
		filter.doFilter(request, response, chain);
	}

}

然后继续修改其他实现了Filter接口的过滤器类:

HTMLFilter类:

public class HTMLFilter implements Filter {

	@Override
 	public void doFilter(Request request, Response response, FilterChain chain) {
  		request.setRequestMsg(
    			request.getRequestMsg().replace("<", "[").replaceAll(">", "]")
  		);//对请求进行过滤
  
  		chain.doFilter(request, response, chain); //继续对请求进行过滤,执行下一个过滤器
  
  		//当对请求过滤完毕后,控制前交到当前过滤器,才会执行对返回的过滤
  		response.setResponseMsg(response.getResponseMsg() + "-->HTMLFilter");
	}
}

SensitiveFilter类:

public class SensitiveFilter implements Filter {

	@Override
 	public void doFilter(Request request, Response response, FilterChain chain) {
  		request.setRequestMsg(
			request.getRequestMsg().replace("敏感", "***")
  		);//对请求进行过滤
  
  		chain.doFilter(request, response, chain); //继续对请求进行过滤,执行下一个过滤器
  
  		//当对请求过滤完毕后,控制前交到当前过滤器,才会执行对返回的过滤
  		response.setResponseMsg(response.getResponseMsg() + "-->SensitiveFilter");
	}
}

FaceFilter类:

public class FaceFilter implements Filter {

	@Override
 	public void doFilter(Request request, Response response, FilterChain chain) {
  		request.setRequestMsg(
    			request.getRequestMsg().replace(":)", "^V^")
  		);//对请求进行过滤
    
  		chain.doFilter(request, response, chain); //继续对请求进行过滤,执行下一个过滤器
  
  		//当对请求过滤完毕后,控制前交到当前过滤器,才会执行对返回的过滤
  		response.setResponseMsg(response.getResponseMsg() + "-->FaceFilter");
	}
}

修改MsgProcessor类:

public class MsgProcessor {
	
	private Request request;
	private Response response;
	private FilterChain chain;
	
	public MsgProcessor(Request request, Response response, FilterChain chain) {
		this.request = request;
		this.response = response;
		this.chain = chain;
	}
	
	public void process() {
		this.chain.doFilter(this.request, this.response, this.chain);
	}

}

最后,即是客户端调用:

public class Client {

	public static void main(String[] args) {
		Request request = new Request("大家好:),<script>,敏感,设计模式,责任链模式");
		Response response = new Response("对返回过滤开始");
		
		FilterChain chain01 = new FilterChain();  //过滤器链01
		chain01.addFilter(new HTMLFilter())
			 .addFilter(new SensitiveFilter());
		
		FilterChain chain02 = new FilterChain();  //过滤器链02
		chain02.addFilter(new FaceFilter());
		 
		chain01.addFilter(chain02);   //往过滤器链01中加入过滤器链02形成新的过滤器链
		
		MsgProcessor processor = new MsgProcessor(request, response, chain01);
		
		processor.process();
		
		System.out.println(request.getRequestMsg());
		System.out.println(response.getResponseMsg());
	}

}

输入如下:

可以发现,对请求和返回过程均实现了过滤,且是先对请求过滤完毕后,再返回进行过滤。

如果在某个过滤器中发现了某个条件不满足,那么还可以直接返回而不继续向下执行,以上代码不变,修改SensitiveFilter如下:

public class SensitiveFilter implements Filter {

	@Override
 	public void doFilter(Request request, Response response, FilterChain chain) {
  		request.setRequestMsg(
   			 request.getRequestMsg().replace("敏感", "***")
  		);//对请求进行过滤
  
  		if(request.getRequestMsg().contains("123")) {//条件
   			chain.doFilter(request, response, chain); //继续对请求进行过滤,执行下一个过滤器
  		}
  
  		//当对请求过滤完毕后,控制前交到当前过滤器,才会执行对返回的过滤
  		response.setResponseMsg(response.getResponseMsg() + "-->SensitiveFilter");
 	}
}

输出如下:可以发现,如果SensitiveFilter后面还有需要执行的逻辑或者过滤器,当条件不满足时就直接返回了,根本不会执行后面的逻辑或过滤器

三、总结

以上就是有关责任链模式的设计,最后的Filter接口是不是和Servlet中的Filter接口类似呢?大笑



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值