責任鏈設計模式應用場景示例(過濾器、攔截器)

責任鏈設計模式(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("<", "&lt;").replace(">", "&gt;");
        //過濾敏感詞
        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("<", "&lt;").replace(">", "&gt;");
 
        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)

責任鏈設計模式(過濾器、攔截器)1838

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,☆很重要)。

責任鏈設計模式(過濾器、攔截器)2890

下面用程序模擬JavaWeb中的過濾器,實現相似於對Request和Response的過濾。主要涉及的類以下所示:

責任鏈設計模式(過濾器、攔截器)2950

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("<", "&lt;").replace(">", "&gt;");
        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);
    }
}
相關文章
相關標籤/搜索