责任链设计模式(Chain of Responsibility)的应用有:Java Web中的过滤器链、Struts2中的拦截器栈。java
先看一个问题:设计模式
给定一个字符串“被就业了:),敏感信息,<script>”,对其中的HTML标记和敏感词进行过滤或替换。
本文主要以该问题设计方法的演变来说解责任链设计模式。测试
第一种设计:没有任何设计模式this
设计了一个MsgProcessor类,完成字符串处理的主要工做。MainClass类是本设计中的测试类。spa
public class MainClass { public static void main(String[] args) { //须要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //实例化处理类 MsgProcessor mp = new MsgProcessor(msg); String r = mp.process(); System.out.println(r); } } public class MsgProcessor { private String msg; public MsgProcessor(String msg){ this.msg = msg; } public String process(){ String r = msg; //过滤msg中的HTML标记 r = r.replace("<", "<").replace(">", ">"); //过滤敏感词 r = r.replace("敏感", "").replace("被就业", "就业"); return r; } }
第二种设计:增长一个Filter接口设计
在第一种设计中,对字符串的全部处理都放在MsgProcessor类中,扩展性极差。若是要过滤字符串中的笑脸(将”:)”替换成”^_^”),则须要改动MSgProcessor中的process方法。code
public interface Filter { String doFilter(String str); } public class HtmlFilter implements Filter { public String doFilter(String msg) { String r = msg; //过滤msg中的HTML标记 r = r.replace("<", "<").replace(">", ">"); return r; } } public class SensitiveFilter implements Filter { public String doFilter(String msg) { String r = msg; //过滤敏感词 r = r.replace("敏感", "").replace("被就业", "就业"); return r; } } public class MsgProcessor { private String msg; private Filter[] filters = {new HtmlFilter(),new SensitiveFilter()}; public MsgProcessor(String msg){ this.msg = msg; } public String process(){ String r = msg; for(Filter f : filters){ r = f.doFilter(r); } return r; } }
此时,若是须要过滤字符串中的笑脸,只须要建立一个类FaceFilter实现Filter接口,并在MsgProcessor类中的filters字段中登记便可。orm
第三种设计:责任链模式(FilterChain)对象
定义:将一个事件处理流程分派到一组执行对象上去,这一组执行对象造成一个链式结构,事件处理请求在这一组执行对象上进行传递。责任链模式的主要参与角色:接口
① 事件处理请求对象(Request)
② 执行对象(Handler)
public class FilterChain implements Filter { public List<Filter> filters= new ArrayList<Filter>(); public FilterChain addFilter(Filter f){ filters.add(f); return this; } public String doFilter(String msg) {//执行filters中的doFilter方法便可 String r = msg; for(Filter f : filters){ r = f.doFilter(r); } return r; } } public class MsgProcessor { private String msg; private FilterChain chain = new FilterChain(); public MsgProcessor(String msg,Filter Chain){ this.msg = msg; this.chain = chain; } public String process(){ return chain.doFilter(msg); } } public class MainClass { public static void main(String[] args) { //须要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //搞一个过过滤链 FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()).addFilter(new SensitiveFilter()); //实例化处理类 MsgProcessor mp = new MsgProcessor(msg,chain); String r = mp.process(); System.out.println(r); } }
责任链模式增强版
上面的实现的过滤链能够用下图a)表示出来,整个过程只对msg过滤了一次。而JavaWeb中的过滤器链和Struts2中的拦截器栈执行的过程能够形象的表示为图b,☆很重要)。
下面用程序模拟JavaWeb中的过滤器,实现相似于对Request和Response的过滤。主要涉及的类以下所示:
public interface Filter { void doFilter(Request req,Response resp,FilterChain chain); } public class HtmlFilter implements Filter { public void doFilter(Request req, Response resp, FilterChain chain) { //过滤req.reqStr中的HTML标记 req.reqStr = req.reqStr.replace("<", "<").replace(">", ">"); req.reqStr += "---HtmlFilter()---"; chain.doFilter(req, resp); resp.respStr += "---HtmlFilter()---"; } } public class SensitiveFilter implements Filter { public void doFilter(Request req, Response resp, FilterChain chain) { // 过滤req.reqStr中的敏感词 req.reqStr = req.reqStr.replace("敏感", "").replace("被就业", "就业"); req.reqStr += "===SensitiveFilter"; chain.doFilter(req, resp); resp.respStr += "===SensitiveFilter"; } } public class FilterChain{ private List<Filter> filters = new ArrayList<Filter>(); //调用链上的过滤器时,记录过滤器的位置用 private int index = 0; public FilterChain addFilter(Filter f){ filters.add(f); return this; } public void doFilter(Request req, Response resp) { if(index == filters.size()) return; //获得当前过滤器 Filter f = filters.get(index); index++; f.doFilter(req, resp, this); } } public class Request { //在Request中只保持了一个reqStr字段记录对Request的操做 //为了方便模拟,没有将reqStr设置为private String reqStr; } public class Response { //在Response中只保持了一个respStr字段记录对Response的操做 //为了方便模拟,没有将respStr设置为private String respStr; } package org.flyne.fiter; public class MainClass { public static void main(String[] args) { // 须要被过滤的语句 String msg = "被就业了:),敏感信息,<script>"; //建立Request、Response对象 Request req = new Request(); Response resp = new Response(); req.reqStr = msg; resp.respStr = "response"; //搞一个过滤链,链上有两个过滤器 FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); //开始过滤 chain.doFilter(req, resp); System.out.println(req.reqStr); System.out.println(resp.respStr); } }