責任鏈設計模式(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); } }