(《設計模式解析與實戰——何紅輝,關愛民》讀書筆記)
一、定義
使多個對象都有機會處理請求,從而避免了請求的發送者和接收者之間的耦合關係。將這些對象連成一條線,並沿着這條鏈傳遞該請求,直到有對象處理它爲止。
這類似於力的傳遞一樣,一環套一環。
二、使用場景
(1)多個對象可以處理同一請求,但具體由哪個對象處理則在運行時動態決定;
(2)在請求處理者不明確的情況下向多個對象中的一個提交一個請求;
(3)需動態指定一組對象處理請求。
三、責任鏈模式的通用模式代碼
簡化版的通用模式代碼:
Handler:抽象處理者角色,聲明一個請求處理的方法,並在其中保持一個對下一個處理節點Handler對象的引用。
ConcreteHandler:具體處理者角色,對請求進行處理,如果不能處理則將該請求轉發給下一個節點上的處理對象。
/**
* 抽象處理者
*/
public abstract class Handler {
/**
* 下一節點處理者
*/
protected Handler successor;
/**
* 請求處理
*
* @param condition
* 請求條件
*/
public abstract void handlerRequest(String condition);
}
/**
* 具體的處理者1
*/
public class ConcreteHandler1 extends Handler{
@Override
public void handlerRequest(String condition) {
if (condition.equals("ConcreteHandler1")) {
System.out.println("我是具體的處理者1");
return;
}else {
successor.handlerRequest(condition);
}
}
}
/**
* 具體的處理者2
*/
public class ConcreteHandler2 extends Handler{
@Override
public void handlerRequest(String condition) {
if (condition.equals("ConcreteHandler2")) {
System.out.println("我是具體的處理者2");
return;
}else {
successor.handlerRequest(condition);
}
}
}
/**
* 客戶端
*/
public class Client {
public static void main(String[] args) {
ConcreteHandler1 handler1 = new ConcreteHandler1();
ConcreteHandler2 handler2 = new ConcreteHandler2();
// 設置handler1的下一節點
handler1.successor = handler2;
// 設置handler2的下一節點
handler2.successor = handler1;
// 處理請求
handler1.handlerRequest("ConcreteHandler2");
}
}
運行結果:
上面的請求條件是一個字符串,然而在大多數情況下,責任鏈中的請求和對應的處理規則是不盡相同的,在這種情況下可以將請求進行封裝,同時對請求的處理規則也進行封裝作爲一個獨立的對象。
**
* 抽象請求者
*/
public abstract class AbstractRequest {
/**
* 處理對象
*/
private Object mObject;
public AbstractRequest(Object object) {
super();
this.mObject = object;
}
/**
* 獲取處理的內容對象
*
* @return 具體的內容對象
*/
public Object getContent() {
return mObject;
}
/**
* 獲取請求級別
*
* @return 請求級別
*/
public abstract int getRequestLevel();
}
/**
* 抽象處理者
*/
public abstract class AbstractHandler {
/**
* 下一節點上的處理者對象
*/
protected AbstractHandler nextHandler;
/**
* 處理請求
*
* @param request
* 請求對象
*/
public final void handlerRequest(AbstractRequest request) {
// 判斷當前處理者對象的處理級別是否與請求者的處理級別一致
if (getHanleLevel() == request.getRequestLevel()) {
// 一致則由該處理對象處理
handle(request);
} else {
// 否則將該請求對象轉發給下一個節點上的請求對象
if (nextHandler != null) {
nextHandler.handlerRequest(request);
} else {
// 當所有處理者對象均不能處理該請求時輸出
System.out.println("All of handler can not handle the request!");
}
}
}
/**
* 獲取處理者對象的具體處理級別
*
* @return 處理級別
*/
protected abstract int getHanleLevel();
/**
* 獲取處理者對象的具體處理方式
*
* @param request
* 請求者對象
*/
protected abstract void handle(AbstractRequest request);
}
/**
* 請求者1
*/
public class Request1 extends AbstractRequest{
public Request1(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 1;
}
}
/**
* 請求者2
*/
public class Request2 extends AbstractRequest{
public Request2(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 2;
}
}
/**
* 請求者3
*/
public class Request3 extends AbstractRequest{
public Request3(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 3;
}
}
/**
* 處理者1
*/
public class Handler1 extends AbstractHandler {
@Override
protected int getHanleLevel() {
return 1;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler1 handle request:" + request.getRequestLevel());
}
}
/**
* 處理者2
*/
public class Handler2 extends AbstractHandler {
@Override
protected int getHanleLevel() {
return 2;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler2 handle request:" + request.getRequestLevel());
}
}
/**
* 處理者3
*/
public class Handler3 extends AbstractHandler {
@Override
protected int getHanleLevel() {
return 3;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler3 handle request:" + request.getRequestLevel());
}
}
/**
* 客戶端
*/
public class Client {
public static void main(String[] args) {
// 構造三個處理者對象
AbstractHandler handler1 = new Handler1();
AbstractHandler handler2 = new Handler2();
AbstractHandler handler3 = new Handler3();
// 設置當前處理者對象下一個節點的處理者對象
handler1.nextHandler = handler2;
handler2.nextHandler = handler3;
// 構造三個請求者對象
AbstractRequest request1 = new Request1("Request1");
AbstractRequest request2 = new Request1("Request2");
AbstractRequest request3 = new Request1("Request3");
// 總是從鏈式的首端發起請求
handler1.handlerRequest(request1);
handler1.handlerRequest(request2);
handler1.handlerRequest(request3);
}
}
運行結果:
當然請求的發起可以從責任鏈的任何一個節點處開始,同時也可以改變責任鏈內部傳遞的規則。
四、優缺點
優點:
可以對請求者和處理者關係解耦,提高代碼的靈活性。
缺點:
對請求處理者的遍歷,如果處理者太多那麼遍歷必定會影響性能,特別是在一些遞歸調用中,要慎重。