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