Java設計模式:責任鏈 – JAVA編程語言程序開發技術文章

責任鏈模式(Chain of Responsibility)的目標是使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,並沿著這條鏈傳遞請求,直到有一個對象處理它為止。

在處理用戶的請求時可能要根據不同的情況對請求添加不同的處理邏輯,在這時候就可以利用責任鏈進行設計。當需要添加一個處理邏輯時可以很方便的添加一個處理的節點。

現在我們的需求是處理用戶的請求,將用戶提交的字符串信息進行層層處理,同時在處理完成之後返回結果時,也要對返回的字符串進行層層處理,而處理返回的情況時其處理的順序和先前是正好相反的順序。

首先建立用戶的請求和接收對象Request和Response:

package com.lcq.filter; 
 
public class Request { 
    String requestStr; 
 
    public String getRequestStr() { 
        return requestStr; 
    } 
 
    public void setRequestStr(String requestStr) { 
        this.requestStr = requestStr; 
    } 
 

package com.lcq.filter; 
 
public class Response { 
    String responseStr; 
 
    public String getResponseStr() { 
        return responseStr; 
    } 
 
    public void setResponseStr(String responseStr) { 
        this.responseStr = responseStr; 
    } 
 

我們將處理用戶信息的邏輯抽象成為一個個的過濾器,進一步抽象出過濾器接口Filter:

package com.lcq.filter; 
 
public interface Filter { 
    public void doFilter(Request request, Response response,FilterChain chain); 
 

註意在Filte接口中doFilter方法參數中有FilterChain的一個變量,我們再建立FilterChain類:

package com.lcq.filter; 
 
import java.util.ArrayList; 
import java.util.List; 
 
public class FilterChain implements Filter { 
    List<Filter> filters = new ArrayList<Filter>(); 
    int index = 0; 
 
    public FilterChain addFilter(Filter f) { 
        this.filters.add(f); 
        return this; 
    } 
 
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) { 
        if (index == filters.size()) 
            return; 
        Filter f = filters.get(index); 
        index++; 
        f.doFilter(request, response, chain); 
    } 

在FilterChain中繼承瞭Filter接口,從而實現瞭doFilter方法,在FilterChain中又有一個index變量,該變量是用來標記當前訪問的是哪一個過濾器,這些過濾器是存放在ArrayList中的,這樣用戶在使用的時候就可以實現自己的過濾器,編寫自己的處理邏輯,從而將自己的過濾器添加到ArrayList中,再調用FilterChain的doFilter方法遍歷整個責任鏈。

下面我們編寫三個過濾器:

HTMLFilter類:

package com.lcq.filter; 
 
/** 
 * 過濾HTML中的腳本元素 
 * @author lcq 
 * 
 */
public class HTMLFilter implements Filter { 
 
    @Override
    public void doFilter(Request request, Response response,FilterChain chain) { 
        request.requestStr = request.getRequestStr().replace("<", "[") 
                .replace(">", "] ——–HTMLFilter"); 
        chain.doFilter(request, response, chain); 
        response.responseStr += "——–HTMLFilter"; 
         
    } 
 

SesitiveFilter類:

package com.lcq.filter; 
 
public class SesitiveFilter implements Filter { 
 
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) { 
        request.requestStr = request.getRequestStr().replace("敏感", "  ") 
                .replace("貓貓", "haha——SesitiveFilter"); 
        chain.doFilter(request, response, chain); 
        response.responseStr += "——SesitiveFilter"; 
 
    } 
 

FaceFilter類:

package com.lcq.filter; 
 
public class FaceFilter implements Filter { 
 
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) { 
        request.requestStr = request.getRequestStr().replace(":)", 
                "^V^——-FaceFilter"); 
        chain.doFilter(request, response, chain); 
        response.responseStr += "——-FaceFilter"; 
 
    } 
 

最後編寫測試類:

package com.lcq.filter; 
 
public class Main { 
    public static void main(String[] args) { 
        String message = "敏感詞匯,重慶,<script> 躲貓貓 :)"; 
        Request request = new Request(); 
        request.setRequestStr(message); 
        Response response = new Response(); 
        response.setResponseStr("response"); 
        FilterChain fc = new FilterChain(); 
        fc.addFilter(new HTMLFilter()).addFilter(new SesitiveFilter()); 
 
        FilterChain fc2 = new FilterChain(); 
        fc2.addFilter(new FaceFilter()); 
        fc.addFilter(fc2); 
        fc.doFilter(request, response,fc); 
        System.out.println("request = " + request.getRequestStr()); 
        System.out.println("response = " + response.getResponseStr()); 
    } 
 

在上面的實例中應該註意兩個地方:

1.我們建立的FilterChain中繼承瞭Filter接口,所以在測試類中就可以像使用其他的過濾器一樣使用FilterChain,大大提高瞭靈活性;

2.對於實現責任鏈的訪問處理順序問題,該問題的解決使用的是遞歸的思想,從而使先調用的結點在處理返回結果時其調用過濾器的順序是相反的。這種解決方案在Struts和其他框架中實現過濾器和攔截器使用的較為普遍,並且十分巧妙。

發佈留言