多維數組 多維數組可以看成是數組的數組,比如二維數組就是一個特殊的一堆數組,其每一個元素都是一個一維數組 二維數組 首先看一下二維數組的定義: int arr[][]=new int[2][3] 上述定義的數組可以看成是一個2行3列的數組。 我們可以寫代碼來看一下關於二維數組的應用。 代碼示例: ...
在現實生活中,一個事件需要經過 多個對象 處理是很常見的場景。比如:採購審批流程、請假流程等。公司員工請假,可批假的領導有部門負責人、副總經理、總經理等,但每個領導能批准的天數不同,員工必鬚根據需要請求的天數去找不同的領導簽名,即員工必須記住每個領導的姓名、電話和地址信息,這使得該流程變得複雜冗餘。
在電腦軟體開發中也有相關的例子,比如 異常處理,處理程式根據異常的類型決定自己是否處理該異常;還有
Struts2
的 攔截器、JSP
、Servlet
的 Filter過濾器等,都可以考慮使用 責任鏈(職責鏈)設計模式 來實現。Servlet
的 Filter過濾器的實現確實使用了 責任鏈設計模式
模式的定義與特點
責任鏈(Chain of Responsibility) 模式的定義:為了避免 請求發送者 與 多個請求處理者 耦合在一起,於是將所有的 請求處理者 通過讓 前一對象 記住 其下一個對象的引用 的方式而形成了一個 鏈條;當有請求發生時,可將請求沿著該 鏈條 傳遞,直到有對象處理當前請求為止。
在 責任鏈模式 中,客戶只需要將請求發送到 責任鏈 上即可,無需關心請求的 處理 和請求的 傳遞過程,請求會 自動 進行傳遞,因此 責任鏈模式 將請求的 發送者 和請求的 處理者 解耦合了
責任鏈模式是一種 對象行為型 模式
主要優點
- 降低了對象之間的 耦合度。該模式使得一個對象無需知道到底是哪一個對象處理其請求,也無需知道 鏈條 的結構,發送者和接收者也無需擁有對方的明確信息
- 增強了系統的 可擴展性。可以根據需要增加新的 請求處理類,符合 開閉原則
- 增強了給對象指派職責的 靈活性。當工作流程發生變化,可以 動態 的改變 鏈條 內的成員或者調動它們的 次序,也可以 動態 的增加或者刪除責任
- 簡化了對象之間的 連接。每個對象只需持有一個指向其後繼者的 引用,不需要持有其它所有處理者的 引用
- 責任 分化。每個類只需處理自己該處理的工作,不該處理的傳遞給下一個對象完成,明確各類的 責任範圍,符合 單一職責原則
主要缺點
- 不能保證請求一定會被處理。由於請求沒有明確的 接收者,所有不能保證它一定會被處理,該請求可能一直傳遞到 鏈條 的末端都得不到處理
- 如果 責任鏈 比較長,請求的處理可能涉及多個處理對象,處理對象過多將會對 系統性能 產生影響
- 責任鏈 建立的 合理性 要靠 客戶端 來保證,增加了客戶端的 複雜性,可能會由於 責任鏈 的錯誤設置而導致 系統出錯,如可能造成 迴圈調用(責任鏈的實現基於 遞歸)
模式的結構與實現
模式的結構
- 抽象處理者(Handler)角色:定義一個處理請求的 介面 或者 抽象類,包含 抽象處理方法 和一個 後繼連接
- 具體處理者(Concrete Handler)角色:實現 抽象處理者 的 處理方法,判斷能否處理本次請求,如果可以處理則處理,否則將請求轉給當前具體處理者的 後繼者
- 客戶類(Client)角色:創建處理鏈(即創建 具體處理者 對象),並向 鏈頭 的具體處理者提交請求,它不關心 處理細節 和請求的 傳遞過程
責任鏈模式 的本質是解耦 請求 與 處理,讓請求在 處理鏈 中能進行 傳遞 與 被處理;理解 責任鏈模式 應該理解其 模式,而不是其具體實現。責任鏈模式 的獨到之處是將其節點處理者組合成了 鏈式結構,並允許節點自身決定是否進行 請求處理 或 轉發,相當於讓請求 流動 起來
- 模式結構圖
- 責任鏈示意圖
模式的實現
- 抽象處理者角色-
Handler
/**
* 抽象處理者
*/
public abstract class Handler {
// 定義後繼者引用
private Handler next;
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
// 定義處理請求的抽象方法
public abstract void handleRequest(String request);
}
- 具體處理者角色-
ConcreteHandler1
、ConcreteHandler2
/**
* 具體處理者1
*/
public class ConcreteHandler1 extends Handler{
@Override
public void handleRequest(String request) {
if("one".equals(request)){ // 具體處理者1能夠處理當前請求
// 具體處理者1對當前請求進行處理
System.out.println("具體處理者1負責處理當前請求,已處理完畢...");
}else { // 具體處理者1不能處理當前請求
if(this.getNext() != null){ // 當前具體處理者1存在後繼者
// 將當前請求發送給當前具體處理者1的後繼者
this.getNext().handleRequest(request);
}else{ // 當前具體處理者1不存在後繼者
// 結束請求,返回
System.out.println("沒有任何處理者處理當前請求,調用結束...");
}
}
}
}
/**
* 具體處理者2
*/
public class ConcreteHandler2 extends Handler{
@Override
public void handleRequest(String request) {
if("two".equals(request)){ // 具體處理者2能夠處理當前請求
// 具體處理者2對當前請求進行處理
System.out.println("具體處理者2負責處理當前請求,已處理完畢...");
}else { // 具體處理者2不能處理當前請求
if(this.getNext() != null){ // 當前具體處理者2存在後繼者
// 將當前請求發送給當前具體處理者2的後繼者
this.getNext().handleRequest(request);
}else{ // 當前具體處理者2不存在後繼者
// 結束請求,返回
System.out.println("沒有任何處理者處理當前請求,調用結束...");
}
}
}
}
- 客戶端角色-
Client
/**
* 客戶端
*/
public class Client {
public static void main(String[] args) {
// 創建具體處理者對象,組裝責任鏈
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
// 設置 handler1(第一個具體處理者對象) 的後繼者為 handler2
handler1.setNext(handler2);
// 提交請求
handler1.handleRequest("two");
}
}
- 程式運行結果:
具體處理者2負責處理當前請求,已處理完畢...
模式的應用場景
- 多個對象 可以處理 同一個請求,但具體由那個對象處理該請求在 運行時 自動確定
- 可 動態 指定一組對象處理請求,或添加新的處理者
- 需要在不明確指定請求處理者的情況下,向多個處理者中的一個提交請求
模式的擴展
- 純的 責任鏈模式:一個請求必須被某一個處理者對象所接收,且一個 具體處理者 對某個請求的處理只能採用 自己處理 或者 交給後繼者處理 兩種方式之一
- 不純的 責任鏈模式:允許出現某一個 具體處理者 對象在承擔了請求的 一部分責任 之後,又將 剩餘的責任 傳遞給 後繼者,且一個請求可以最終不被任何 接收端對象 所接收(Filter過濾器屬於 不純 的責任鏈模式)
文章轉載於:http://c.biancheng.net/view/1383.html