【設計模式】Filter-Chain 的應用

Filter-Chain模式簡介

從7月份實習以來,因爲項目中運用alibaba DRUID 數據庫中間件、Spring Framework等開源框架,所以就稍微閱讀了部分源碼,果然優秀的架構就是優秀的架構,學習裏面對設計模式的應用,應該會對設計模式有更加深刻的理解。

Druid中增加模塊就是通過Filter-Chain模式實現的,任何模塊只要實現Filter接口裏定義的方法,並在初始化時add,就可以對數據的Connection、Statement、ResultSet等做出處理。

下面用一個很簡單的demo簡單演示filter-chain模式的執行過程:

定義Filter接口

public interface Filter {
	void doFilter(MyRequest request,MyResponse response,FilterChain chain);

}
其中MyRequest和MyResponse 是自定義類型,模擬請求過程,當然MyRequest和MyResponse可以被替換成任意一種類型。

public class MyRequest {
	StringBuffer content;
	
	public MyRequest() {
		content = new StringBuffer("request");
	}
	
	public MyRequest(String content){
		this.content = new StringBuffer(content);
	}

	public StringBuffer getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = new StringBuffer(content);
	}
	
	public void append(String append){
		this.content.append(append);
	}
	
	

}

public class MyResponse {
	private StringBuffer content;
	
	public MyResponse() {
		content = new StringBuffer("response");
	}
	
	public MyResponse(String content){
		this.content = new StringBuffer(content);
	}

	public StringBuffer getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = new StringBuffer(content);
	}
	
	public void append(String append){
		this.content.append(append);
	}
	
}


實現Filter接口

每一個具體的Filter實現Filter接口中定義的doFilter方法,並在方法體中封裝處理邏輯。

第一個具體的Filter類,這裏完全簡化處理邏輯,需要根據具體場景定義處理邏輯。實現類處理完自身職責範圍的邏輯後,將對象傳遞給FilterChain,調用FilterChain的DoFilter方法,FilterChain做爲中介將對象傳遞給下一個Filter,稍後我們來看FilterChain這個類的實現。

public class FirstFilter implements Filter{

	@Override
	public void doFilter(MyRequest request, MyResponse response, FilterChain chain) {
		request.append(" firsrt Filter || ");
		chain.doFilter(request, response);
		response.append(" firsrt Filter || ");
	}

}

第二個具體的Filter類:

public class SecondFilter implements Filter{

	@Override
	public void doFilter(MyRequest request, MyResponse response, FilterChain chain) {
		request.append("second filter || ");
		chain.doFilter(request, response);
		response.append("second filter || ");
	}

}

FilterChain的實現

filterChain持有一個List<Filter>的引用,並通過一個pos標誌位標記執行到哪一個Filter,Chain的DoFilter方法實際上就是將對象傳遞給Filter,並將標誌位+1,指向下一個將要執行的Filter。
public class FilterChain{
	private List<Filter> filters;
	int pos = 0;
	
	public FilterChain() {
		filters = new LinkedList<>();
	}
	
	public void addFilter(Filter filter){
		filters.add(filter);
	}

	public void doFilter(MyRequest request, MyResponse response) {
		if(pos < filters.size()){
			filters.get(pos++).doFilter(request, response, this);
		}
		
	}

}

兩種實現方式

上面所述的實現方式是Tomcat、Spring、java web api中的實現方式。當然更簡單的實現方式是每個filter持有下一個filter的引用,處理完之後直接調用nextFilter的方法,直到執行完畢。顯然第二種在編碼上更簡單也更容易理解。那爲什麼許多java框架要採用第一種設計呢?個人認爲第一種顯然在可擴展上要優於第二種實現。FilterChain持有Filter的列表,自然擁有對所有Filter的管理和控制。這樣就把對整個filter-Chain鏈的管理集中在一個地方,實現了維護和擴展的方便。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章