#責任鏈(ChainOfResponsibility)java
對於設計模式的學習,必定要動手,並且要屢次練習,而後慢慢消化和理解,才能明白其精髓。可是,設計模式只是在特殊情景下的特殊解決方案,不要濫用,不要爲了使用設計模式而硬生生得去使用。設計模式的使用應該天然、優雅!web
public class TestMain { public static void main(String[] args) { String str = "你好:),這句話中有敏感詞彙,須要處理。<script>,敏感!"; MsgProcessor pro = new MsgProcessor(); pro.setMsg(str); str = pro.processor();--- System.out.println(str); } }
另外一個類:編程
public class MsgProcessor { private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String processor(){ String content = ""; if(null != msg && !("").equals(msg.trim())){ content = msg.replace("<", "{") .replace(">", "}"); content = content.replace("敏感", ""); content = content.replace(":)", "^V^"); } return content; } }
上面的代碼完成了對一個字符串的簡單過濾,可是很明顯這樣的代碼很很差。擴展性很差,寫得也不夠好。這樣之後須要添加別的過濾功能不是很方便,老是要修改這個類,一點都不靈活,想把對字符串的過濾行爲抽象出來,由於這部分是變化的,天然而然想到使用接口。設計模式
代碼修改成:數組
public String processor(){ if(null != msg && !("").equals(msg.trim())){ msg = new HTMLFilter().doFilter(msg); msg = new SmileFilter().doFilter(msg); msg = new SensitivityFilter().doFilter(msg); } return msg; }
這樣仍是不夠靈活,直接在 ** MsgProcessor ** 類中添加一個數組來保存過濾器,而後在 ** processor** 方法中進行屢次調用:數據結構
修改成:ide
public String processor(){ if(null != msg && !("").equals(msg.trim())){ for(Filter f : filters){ msg = f.doFilter(msg); } } return msg; }
這樣調整後,全部的過濾器都起做用了,添加起來更加靈活一些,而且過濾器的執行順序也是可控的。學習
當多個過濾器組合在一塊兒,就造成了過濾器鏈,到這裏,責任鏈有點雛形了。this
若是原本已經存在一個過濾器鏈條了,我想把一些新的過濾器鏈加進去,而且加入的順序能夠隨意控制(隨意組合任意的過濾器鏈條),該怎麼辦呢?設計
定義一個過濾器鏈類,這這個類中定義添加過濾器的方法,以及運行整個鏈條上的全部過濾器的方法,而且返回結果。
代碼修改成:
MsgProcessor.java :
public class MsgProcessor { private String msg; private FilterChain fc; public FilterChain getFc() { return fc; } public void setFc(FilterChain fc) { this.fc = fc; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String processor(){ return fc.doFilter(msg); } }
FilterChain.java:
public class FilterChain { List<Filter> filters = new ArrayList<Filter>(); public FilterChain addFilter(Filter filter){ filters.add(filter); return this; } public String doFilter(String str){ if(null != str && !("").equals(str.trim())){ for(Filter f : filters){ str = f.doFilter(str); } } return str; } }
TestMain.java
public class TestMain { public static void main(String[] args) { String str = "你好:),這句話中有敏感詞彙,須要處理。<script>,敏感!"; MsgProcessor mp = new MsgProcessor(); mp.setMsg(str); FilterChain fc = new FilterChain(); fc.addFilter(new HTMLFilter()) .addFilter(new SmileFilter()) .addFilter(new SensitivityFilter()); mp.setFc(fc); str = mp.processor(); System.out.println(str); } }
寫到這裏,仍是沒有解決咱們的問題,怎樣靈活合併過濾器鏈呢? 很簡單,咱們能夠將過濾器鏈這個類,看成一個很大的過濾器來處理,這樣就能夠了。讓** FilterChain **也實現Filter接口,這樣就解決了這個問題!完成這一步,就已經有了責任鏈模式的味道了!
在實際開發中,咱們見過的過濾器都能進行雙向的處理,也就是說,能處理request和response,並且是先挨着處理request,而後再反向處理response,這又是怎麼實現的呢?
定義一個Request和Response,在實際的web容器中,容器會幫助咱們生成這兩個對象,並且在其中封裝了不少的東西,在這裏,只是模擬,只需簡單定義就能夠了。
Request.java
public class Request { private String requestStr; public String getRequestStr() { return requestStr; } public void setRequestStr(String requestStr) { this.requestStr = requestStr; } }
Response.java
public class Response { private String responseStr; public String getResponseStr() { return responseStr; } public void setResponseStr(String responseStr) { this.responseStr = responseStr; } }
定義好這兩個類以後,修改以前的程序:
Filter.java
public interface Filter { public abstract void doFilter(Request request, Response response); }
別的代碼跟着這個接口一塊兒改就能夠了,可是你會發現,仍是不能實現咱們想要的效果,這個時候須要一些編程的手法,咱們繼續修改Filter接口:
Filter.java
public interface Filter { public abstract void doFilter(Request request, Response response, FilterChain filterChain); }
爲何要這樣修改,由於只有這樣才能把鏈條握在每個過濾器手中,有了鏈條,就能夠控制鏈條了:
FilterChain.java
public class FilterChain implements Filter { private List<Filter> filters = new ArrayList<Filter>(); private int index = 0; public FilterChain addFilter(Filter filter){ this.filters.add(filter); return this; } @Override public void doFilter(Request request, Response response, FilterChain filterChain) { if(index >= filters.size()) return; Filter f = filters.get(index); index++; f.doFilter(request, response, filterChain); } }
HTMLFilter.java
public class HTMLFilter implements Filter { @Override public void doFilter(Request request, Response response, FilterChain filterChain) { String str = request.getRequestStr(); System.out.println(str); filterChain.doFilter(request, response, filterChain); String resStr = response.getResponseStr(); System.out.println(resStr); } }
如今來看,每一個過濾器都持有過濾器鏈,在處理完request後,調用下一個過濾器,因爲方法是棧結構,這樣就會造成一個過濾器棧,擁有棧的數據結構特色。這也是爲何Struts在配置多個攔截器的時候,成爲攔截器棧的緣由。 因爲棧的數據特色,就能達到咱們想要的特色,按照過濾器的次序,依次處理完request,而後再反向依次處理response。這就是責任鏈模式在實際開發中的使用。