JAVA設計模式之 職責鏈模式【Chain of Responsibility Pattern】

小呂-ICE發表於2014-11-26

一、概述

    避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止。職責鏈模式是一種物件行為型模式

    核心在於引入一個抽象處理者類


二、適用場景

    請求的鏈式處理,多個物件可以處理同一請求、但是具體由哪個物件來處理由執行時系統根據條件判斷確定。

   如請假業務場景:

    

三、UML類圖

    

四、參與者

1、Handler(抽象處理者):它定義了一個處理請求的介面,一般設計為抽象類,由於不同的具體處理者處理請求的方式不同,因此在其中定義了抽象請求處理方法。因為每一個處理者的下家還是一個處理者,因此在抽象處理者中定義了一個抽象處理者型別的物件(如結構圖中的nextHandler),作為其對下家的引用。通過該引用,處理者可以連成一條鏈。

2、ConcreteHandler(具體處理者):它是抽象處理者的子類,可以處理使用者請求,在具體處理者類中實現了抽象處理者中定義的抽象請求處理方法,在處理請求之前需要進行判斷,看是否有相應的處理許可權,如果可以處理請求就處理它,否則將請求轉發給後繼者;在具體處理者中可以訪問鏈中下一個物件,以便請求的轉發。


注意:職責鏈模式並不建立職責鏈,職責鏈的建立工作必須由系統的其他部分來完成,一般是在使用該職責鏈的客戶端中建立職責鏈。


五、用例學習

1、抽象處理者類:Handler.java

/**
 * 抽象處理者類
 * @author  lvzb.software@qq.com
 *
 */
public abstract class Handler {
	
	protected Handler nextHandler;
	
	public void setNextHandler(Handler nextHandler){
		this.nextHandler = nextHandler;
	}
	
	public abstract void handleRequest(int request);

}
2、具體處理者類A:部門組長 ConcreteHandlerA.java

/**
 * 具體職責處理者A:案例中的 部門組長角色
 * @author  lvzb.software@qq.com
 *
 */
public class ConcreteHandlerA extends Handler {

	@Override
	public void handleRequest(int leaveDay) {
		if(leaveDay <= 1){
			// 滿足處理條件  處理請求
			System.out.println("請假天數小於2天  由部門組長審批");
		} else {
			nextHandler.handleRequest(leaveDay);
		}

	}

}
3、具體處理者類B:部門經理 ConcreteHandlerB.java

/**
 * 具體職責處理者B:案例中的 部門經理角色
 * @author  lvzb.software@qq.com
 *
 */
public class ConcreteHandlerB extends Handler {

	@Override
	public void handleRequest(int leaveDay) {
		if(1 < leaveDay && leaveDay <= 5){
			// 滿足處理條件  處理請求
			System.out.println("請假天數大於1天且小於等於5天  由部門經理審批");
		} else {
			nextHandler.handleRequest(leaveDay);
		}

	}

}
4、具體處理者類C:總經理 ConcreteHandlerC.java

/**
 * 具體職責處理者C:案例中的 總經理角色
 * @author  lvzb.software@qq.com
 *
 */
public class ConcreteHandlerC extends Handler {

	@Override
	public void handleRequest(int leaveDay) {
		if(leaveDay > 5){
			System.out.println("當請假天數大於5天的情況下 由總經理親自操刀審批。總經理的職責已經是最大的啦,還有他沒有許可權處理的事嗎?");
		}
	}

}
5、客戶端類:Client.java

/**
 * 客戶端類<br/>
 * 負責建立職責鏈和傳送請求<br/>
 * 當職責鏈(職責的傳遞順序/請求的處理順序)建好之後,客戶端只負責將請求傳送出去,
 * 而具體請求在職責鏈上的傳遞和最終由鏈上的哪個物件進行處理不由客戶端關心
 * @author  lvzb.software@qq.com
 *
 */
public class Client {

	public static void main(String[] args) {
		Handler handlerA,handlerB,handlerC;
		handlerA = new ConcreteHandlerA();
		handlerB = new ConcreteHandlerB();
		handlerC = new ConcreteHandlerC();
		
		// 建立職責鏈  handlerA ——> handlerB ——> handlerC
		handlerA.setNextHandler(handlerB);
		handlerB.setNextHandler(handlerC);
		
		// 傳送請假請求一
		handlerA.handleRequest(1);
		
		// 傳送請假請求二
		handlerA.handleRequest(7);
		
		// 傳送請假請求二
		handlerA.handleRequest(3); 
	}

}
6、執行結果:

請假天數小於2天  由部門組長審批
當請假天數大於5天的情況下 由總經理親自操刀審批。總經理的職責已經是最大的啦,還有他沒有許可權處理的事嗎?
請假天數大於1天且小於等於5天  由部門經理審批




相關文章