故名思義責任鏈模式中存在一個鏈式結構,鏈式結構:多外節點首尾相連,每個節點都可以被拆分再連接。具體什么是責任鏈模式呢。它使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關系,將這個對象連成一條鏈,并沿著這個條鏈傳遞該請求,直到有一個對象處理它為止。將每一個節點看作是一個對象,每一個對象擁有不同的處理邏輯,將一個請求從鏈式的首段發出,沿著鏈的路徑傳遞給每一個節點對象,直到有對象處理這個請求為止。
責任鏈模式看起來可能比較陌生,可是我們在日常開發卻經常碰到這種形式。
public void handleSomething(int eventNum){
switch (eventNum){
case 1:
//do something
break;
case 2:
//do something
break;
case 3:
//do something
break;
default:
//do something
}
}
switch或者if-else這種就是責任鏈的裸體樣式,是最簡單的實現格式。當然這是個不恰當的例子,if-else嵌套太多,很可能你都看不懂你的代碼。
舉個粟子
下面給一個簡單的例子:
這個例子很簡單,一個抽象的Handler(處理者角色)和一個繼承Handler的具體實現者ConcreteHandler。
類圖
類圖
代碼
Handler類:
public abstract class Handler {
/**
* 持有下一個處理節點
*/
protected Handler successor;
/**
* 這個方法是具體的請求處理方法,在這里為了簡化而沒有傳入參數
*/
public abstract void handleRequest();
/**
* 取出下一個節點的方法
*/
public Handler getSuccessor() {
return successor;
}
/**
* 賦值下一個節點的方法
*/
public void setSuccessor(Handler successor) {
this.successor = successor;
}
}
ConcreteHandler 類:
public class ConcreteHandler extends Handler {
@Override
public void handleRequest() {
/**
* 判斷是否有下個節點的責任處理對象
* 如果有,就轉發請求給下一個責任處理對象
* 如果沒有,則處理請求
*/
if (getSuccessor() != null) {
System.out.println("放過請求");
getSuccessor().handleRequest();
} else {
System.out.println("處理請求");
}
}
}
Cilent類:
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
handler1.handleRequest();
}
}
Android/java 中應用責任鏈模式的場景
- 在android比較明顯的就是事件分發過程中對事件的投遞。嚴格說來,事件投遞并不是嚴格的責任鏈模式,是責任鏈模式的變種實現。子 View 的 onTouchEvent 返回 true 代碼消費該事件并不再傳遞,false 代表不消費并且傳遞到父 ViewGroup 去處理,這些樹形結構的子 View 就是責任鏈上一個個處理對象;
- OrderedBroadcast,廣播的每一個接收者按照優先級依次接受消息,如果處理完成之后可以調用 abortBroadcast 終止廣播,不是自己處理的就可以傳遞給下一個處理者;
- try-catch語句,每一個 catch 根據 Exception 類型進行匹配,形成一個責任鏈,如果有一個 catch 語句與該 Exception 符合,這個 Exception 就交由給它進行處理,之后所有 catch 語句都不會再次執行。
再來看看具體的粟子
如果一個程序員一個月連續加班,這個月算下來可以調休5天。然后這個coder寫了調休申請給項目經理,可項目經理有點方了,他只能審批調休一天的,然后項目經理把你的申請交給部門經理,部門經理一看也沒法,公司規則多,他只能審批多超過三天的,只能讓總經理過目了。
那看看具體代碼。
//這個是leader的抽象類
public abstract class Leader {
private Leader successor;
private int hoildayNum;
private String position;
public void setPosition(String position) {
this.position = position;
}
public String getPosition() {
return position;
}
public Leader(int hoildayNum) {
this.hoildayNum = hoildayNum;
}
public abstract void reply(Worker worker);
public void handleRequest(Worker worker) {
if (worker.getHolidayNum() <= hoildayNum) {
reply(worker);
} else {
if (null != successor) {
successor.handleRequest(worker);
} else {
System.out.println(position + "拒絕了你的請求");
}
}
}
public void setSuccessor(Leader successor) {
this.successor = successor;
}
}
/**
* 項目經理處理類
*/
public class ProjectDirector extends Leader {
public ProjectDirector(int hoildayNum) {
super(hoildayNum);
setPosition("項目經理");
}
@Override
public void reply(Worker worker) {
System.out.println(getPosition() + "已通過你的請求");
}
}
/**
* 部門經理處理類
*/
public class DepartmentManager extends Leader {
public DepartmentManager(int hoildayNum) {
super(hoildayNum);
setPosition("部門經理");
}
@Override
public void reply(Worker worker) {
System.out.println(getPosition() + "已通過你的請求");
}}
/**
* 總經理處理類
*/
public class GeneralManager extends Leader {
public GeneralManager(int hoildayNum) {
super(hoildayNum);
setPosition("總經理");
}
@Override
public void reply(Worker worker) {
System.out.println(getPosition() + "已通過請求");
}
}
public class Cilent {
public static void main(String[] args) {
Worker worker = new Worker(6);
Leader projectDir = new ProjectDirector(1);
Leader departmentMan = new DepartmentManager(3);
Leader generalMan = new GeneralManager(10);
projectDir.setSuccessor(departmentMan);
departmentMan.setSuccessor(generalMan);
projectDir.handleRequest(worker);
}
}
這樣我們就把請求者與處理者優雅的解耦。
純與不純的責任鏈模式
很多資料中會介紹純和不純的責任鏈模式,在標準的責任鏈模式中,責任鏈上的一個節點只允許有兩個行為:處理或者推給下個節點處理,而不允許處理完之后又推給下個節點,前者被很多資料稱為純的責任鏈模式,而后者被稱為不純的責任鏈模式。其實在實際的系統里,純的責任鏈很難找到。如果堅持責任鏈不純便不是責任鏈模式,那么責任鏈模式便不會有太大意義了。