1. 程式人生 > >【設計模式】責任鏈3-橫刀植入

【設計模式】責任鏈3-橫刀植入

緊接著上一篇的開始:
我們來說說普遍的解決方案,我們用一個類來模擬:
這個類模擬一個夠過濾器鏈條:
package cn.edu.hpu.responsibility;


import java.util.List;
import java.util.ArrayList;


public class FilterChain {
	List<Filter> filters=new ArrayList<Filter>();
	
	//返回值是FilterChain只為了在Main中滿足鏈條式的程式設計
	public FilterChain addFilter(Filter f) {
		this.filters.add(f);
		return this;
	}
}

可以新增過濾器。
我們如果把這個過濾器鏈條類看成一個“黑盒子”的話,它也算是一個巨大的過濾器。
於是它也應該有這個方法:
public String doFilter(String str) {
	String r=str;
	for(Filter f:filters){
		r=f.doFilter(r);
        }
		
	return r;
}
也就是:
package cn.edu.hpu.responsibility;

import java.util.List;
import java.util.ArrayList;


public class FilterChain {
	List<Filter> filters=new ArrayList<Filter>();
	
	//返回值是FilterChain只為了在Main中滿足鏈條式的程式設計
	public FilterChain addFilter(Filter f) {
		this.filters.add(f);
		return this;
	}
	
	public String doFilter(String str) {
		String r=str;
		for(Filter f:filters){
			r=f.doFilter(r);
		}
		
		return r;
	}
}

當我們有FilterChain這個類的時候,MsgProcessor就會有些變化:
package cn.edu.hpu.responsibility;

public class MsgProcessor {
	private String msg;
	
	//把眾多的過濾規則(不同的過濾器)整合在一起
	//Filter[] filters={new HTMLFilter(),new SesitiveFilter()};
	FilterChain fc;
	
	public String getMsg() {
		return msg;
	}


	public void setMsg(String msg) {
		this.msg = msg;
	}
	
	public FilterChain getFc() {
		return fc;
	}


	public void setFc(FilterChain fc) {
		this.fc = fc;
	}


	public String process(){
		//處理指令碼語句和敏感字眼
		return fc.doFilter(msg);
	}
}

在Main中就應該這麼寫了:
package cn.edu.hpu.responsibility;


public class Main {
	public static void main(String[] args) {
		String msg="大家好:),<script>,偷盜,搶劫,我們要把設計模式學好";
		MsgProcessor mp=new MsgProcessor();
		mp.setMsg(msg);
		FilterChain fc=new FilterChain();
		fc.addFilter(new HTMLFilter())
		  .addFilter(new SesitiveFilter());//鏈條式寫法
		mp.setFc(fc);
		String result=mp.process();
		System.out.println(result);
	}
}
執行結果:
大家好:),[script],和諧,幫助,我們要把設計模式學好


然後你不想要那個過濾規則了,就把.addFilter(new XxxxxFilter())去掉。或者寫在配置檔案裡,直接改寫配置檔案就可以了。


過程解析圖(FilterChain結構圖):


接下來問題就是,我如何在原來的FilterChain中加入另外一個FilterChain呢?
很簡單,讓FilterChain去實現Filter介面:
public class FilterChain implements Filter{.......

現在我們加一個笑臉過濾器:
package cn.edu.hpu.responsibility;

public class FaceFilter implements Filter {


	@Override
	public String doFilter(String str) {
		//笑臉過濾器
		String r=str.replace(":)", "^_^");
		return r;
	}


}

假設笑臉處理器屬於第二個過濾器鏈條(FilterChain),我們在Main中來組合它們:
package cn.edu.hpu.responsibility;

public class Main {
	public static void main(String[] args) {
		String msg="大家好:),<script>,偷盜,搶劫,我們要把設計模式學好";
		MsgProcessor mp=new MsgProcessor();
		mp.setMsg(msg);
		FilterChain fc=new FilterChain();
		fc.addFilter(new HTMLFilter())
		  .addFilter(new SesitiveFilter());//鏈條式寫法
		
		FilterChain fc2=new FilterChain();
		fc2.addFilter(new FaceFilter());
		
		fc.addFilter(fc2);
		mp.setFc(fc);
		String result=mp.process();
		System.out.println(result);
	}
}
測試結果:
大家好^_^,[script],和諧,幫助,我們要把設計模式學好

下面我們考慮是這樣的,在這裡我們只是訊息從過濾鏈這頭髮到了過濾鏈那頭,直白點就是從客戶端發到伺服器端,一般來說伺服器端也會給客戶端一個反饋。那麼假如說我想做一個從客戶端到伺服器端的過濾且從伺服器端到客戶端的過濾的鏈條,可行嗎?如何實現?

重新寫一些過濾器倒著去過濾伺服器端的資訊也不是不可以,但是程式碼會冗餘。
我們的過濾器應該既處理過去的訊息,又處理回來的訊息。

好了,這樣的程式碼該如何組織呢?

思路:
我們先寫兩個類,一個封裝請求,一個封裝反饋(模擬JavaWeb):
Request和Response類
package cn.edu.hpu.filter.web;


public class Request {
	private String requestStr;


	public String getRequestStr() {
		return requestStr;
	}


	public void setRequestStr(String requestStr) {
		this.requestStr = requestStr;
	}
	
	
}

package cn.edu.hpu.filter.web;


public class Response {
	private String responseStr;


	public String getResponseStr() {
		return responseStr;
	}


	public void setResponseStr(String responseStr) {
		this.responseStr = responseStr;
	}
	
}

現在我們的想法是這樣的,如果我們把Request物件和Response物件交給處理器的話,這個處理器既能把request物件處理,又能處理回來的response物件。這個事情該怎麼辦呢?