設計模式之責任鏈(ChainOfResponsibility)

#責任鏈(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。這就是責任鏈模式在實際開發中的使用。

相關文章
相關標籤/搜索