Java職責鏈模式

職責鏈模式中有多個能夠處理請求的對象RequestHandler,這些處理對象按照先後順序連接成一條處理鏈。在發送請求時只需要把請求傳遞給排在鏈表頭部的RequestHandler對象,請求對象會在處理鏈內部傳遞最終由某個RequestHandler對象處理,也可能最終不處理。

現在假設程序員(Programmer)遇到一個自己解決不了的問題,他會把問題交給自己的組長(Leader)幫忙解決,組長也解決不了就提交給主管(Manager)解決,主管解決問題然後返回給組長,組長在把解決的結果返回給程序員。

public class Request { // 請求對象
	public String req;
}
public class Response { // 響應對象
	public String resp;
}
public interface RequestHandler { // 請求處理接口
	public Response handle(Request request);
}

// 程序員無法處理,提交責任鏈的下一個處理者
class Programmer implements RequestHandler {
	private RequestHandler next; // 下一個處理對象
	
	public void setNext(RequestHandler handler) {
		this.next = handler;
	}
	
	@Override
	public Response handle(Request request) {
		if (next != null) { // 傳遞給下一個處理者
			request.req += "Programmer請求\n";
			Response resp = next.handle(request);
			resp.resp = resp.resp + "Programmer同意\n";
			return resp;
		}
		return null;
	}
}

// Leader無法處理,提交給Manager處理
class Leader implements RequestHandler {
	private RequestHandler next; // 下一個處理對象
	
	public void setNext(RequestHandler handler) {
		this.next = handler;
	}
	
	@Override
	public Response handle(Request request) {
		if (next != null) { // 傳遞給下一個對象處理
			request.req += "Leader請求\n";
			Response resp = next.handle(request);
			resp.resp = resp.resp + "Leader同意\n";
			return resp;
		}
		return null;
	}
}

// Manager能夠處理問題,直接處理
class Manager implements RequestHandler {
	private RequestHandler next;
	
	public void setNext(RequestHandler handler) {
		this.next = handler;
	}
	
	@Override
	public Response handle(Request request) {
		Response resp = new Response(); // Manager處理問題
		resp.resp = request.req + "Manager已解決\n";
		return resp;
	}
}

上面的示例定義了Programmer、Leader和Manager三個問題處理者,Request代表問題請求,Response代表處理結果,現在在測試代碼中將Programmer的下一個處理者設置爲Leader,Leader的下一位處理者設置爲Manager,然後創建問題對象Request給Programmer對象。

Programmer programmer = new Programmer();
Leader leader = new Leader();
Manager manager = new Manager();
// 使用setNext()方法設置職責鏈處理對象鏈接
programmer.setNext(leader);
leader.setNext(manager);

Request request = new Request();
request.req = "OutOfMemory\n";
Response resp = programmer.handle(request); // programmer對象處理問題
System.out.println(resp.resp);

運行上面的測試用例,從執行結果中可以看到請求對象先通過Programmer傳遞給了Leader,再由Leader傳遞給Manager,Manager解決後在將處理結果返回給Leader,Leader加上自己的處理意見後在返回給Programmer,Request問題通過職責鏈完美的解決了。

OutOfMemory
Programmer請求
Leader請求
Manager已解決
Leader同意
Programmer同意

如果讀者使用過OkHttp的網絡攔截器就會發現上面的職責鏈模式和網絡請求響應攔截器非常地類似,在OkHttp網絡請求時Request代表網絡請求數據,用戶可以通過添加用戶攔截器或者網絡攔截器爲網絡請求對象添加通用的參數或者修改返回網絡數據。

假設現在又有了新的問題,公司要求開發一個新的移動應用,主管在接收到公司的項目需求後開始準備立項,接着再把任務交給組長做詳細設計,組長做完詳細設計之後再交給程序員編寫項目代碼,如果還是用前面的實現就需要調整每個處理類中的代碼,還要重新爲它們設置職責鏈的下一個處理對象;假如公司爲了減少無效溝通,允許程序員遇到無法處理的問題直接找到主管處理,不再需要經過組長這一步,或者公司內部在組長和主管之間又增加技術經理,之前的職責鏈又需要不斷地調整處理對象的先後順序,總結來說前面的通過setNext()設置職責鏈非常不靈活。

爲了解決之前職責鏈靈活性不足的問題,引入新的Chain職責鏈對象,在Chain對象中包含所有能夠處理請求的對象,Chain對象中保存一個索引值,該索引值代表當前職責鏈的下一個請求處理對象的位置,不過RequestHandler接口的方法參數也需要加上Chain對象。

public interface ChainRequestHandler {
	public Response handle(Chain chain, Request request);
}

class Programmer implements ChainRequestHandler {
	@Override
	public Response handle(Chain chain, Request request) {
		request.req += "Programmer請求\n";
		Response resp = chain.handle(request);
		resp.resp = resp.resp + "Programmer同意\n";
		return resp;
	}
}

class Leader implements ChainRequestHandler {
	@Override
	public Response handle(Chain chain, Request request) {
		request.req += "Leader請求\n";
		Response resp = chain.handle(request);
		resp.resp = resp.resp + "Leader同意\n";
		return resp;
	}
}

class Manager implements ChainRequestHandler {
	@Override
	public Response handle(Chain chain, Request request) {
		Response resp = new Response();
		resp.resp = request.req + "Manager已解決\n";
		return resp;
	}
}

class Chain implements RequestHandler {
	private List<ChainRequestHandler> handlers;
	private int index;
	public Chain() {
		this.handlers= new ArrayList<>();
		handlers.add(new Programmer());
		handlers.add(new Leader());
		handlers.add(new Manager());
		index = -1;
	}

	@Override
	public Response handle(Request request) {
		if (index >= handlers.size() - 1) {
			return null;
		}
		index++; // 使用下一個處理器對象
		return handlers.get(index).handle(this, request);
	}
}

注意上面的Chain輔助對象,它內部包含了所有需要處理問題對象,通過索引值標識Chain中下一個要處理的對象,像前面提到的需要調整程序員、組長和主管的處理次序,可以通過簡單的調整handlers對象加入順序來實現靈活的責任鏈配置。

Chain chain = new Chain();
Request request = new Request();
request.req = "OutOfMemory\n";
 // 從handlers裏第一個不斷向後傳遞問題請求
Response resp = chain.handle(request); 
System.out.println(resp.resp);

運行增加了Chain對象的職責鏈處理,返回的結果和之前靜態代碼設置職責鏈的效果相同。

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