1 模式動機
為了降低系統的耦合度,將事件請求者和接收者解耦,我們可以使用命令模式來設計系統。通過增加不同的命令對象,不僅可以解耦,也可以有效解決發送和接收處理速度不一樣的問題。
2 模式定義
責任鏈模式(Chain of Responsibility Pattern):將多個對象連成一條鏈,沿着這條鏈傳遞請求,直到有一個對象處理它為止,使得多個對象都有機會處理該請求。
3 模式分析
Handler處理者接口:
聲明處理請求的接口。
ConcreteHandler具體處理者類:
實現處理請求的接口,指定下一處理者。
Client:
調用客戶。
類圖如下所示:
4 實例演示
1 package com.pattern.responsibility; 2 3 public abstract class Handler { 4 public Handler successor = null; 5 6 public abstract boolean canHandle(); 7 8 public abstract void handle(); 9 10 public void handleRequest() { 11 if(canHandle()) { 12 handle(); 13 } else { 14 getSuccessor().handleRequest(); 15 } 16 } 17 18 public Handler getSuccessor() { 19 if(successor==null) { 20 successor = new EmptyHandler(); 21 } 22 return successor; 23 } 24 25 public void setSuccessor(Handler successor) { 26 this.successor = successor; 27 } 28 }
1 package com.pattern.responsibility; 2 3 public class CommonHandler extends Handler { 4 @Override 5 public boolean canHandle() { 6 // 是否可以處理請求 7 System.out.println("Common not handle..."); 8 return false; 9 } 10 11 @Override 12 public void handle() { 13 System.out.println("Common handle..."); 14 } 15 }
1 package com.pattern.responsibility; 2 public class SpecialHandler extends Handler { 3 @Override 4 public boolean canHandle() { 5 // 具體handler實現 6 System.out.println("Special not handle..."); 7 return false; 8 } 9 10 @Override 11 public void handle() { 12 System.out.println("Special handle..."); 13 } 14 }
1 package com.pattern.responsibility; 2 3 public class ExtendHandler extends Handler { 4 @Override 5 public boolean canHandle() { 6 // 是否可以處理請求 7 return true; 8 } 9 10 @Override 11 public void handle() { 12 System.out.println("Extend handle..."); 13 } 14 }
1 package com.pattern.responsibility; 2 3 public class EmptyHandler extends Handler { 4 @Override 5 public boolean canHandle() { 6 // 是否可以處理請求 7 return true; 8 } 9 10 @Override 11 public void handle() { 12 // TODO Auto-generated method stub 13 } 14 }
1 package com.pattern.responsibility; 2 3 public class Client { 4 public static void main(String args[]) { 5 CommonHandler commonHandler = new CommonHandler(); 6 SpecialHandler specialHandler = new SpecialHandler(); 7 ExtendHandler extendHandler = new ExtendHandler(); 8 9 commonHandler.setSuccessor(specialHandler); 10 specialHandler.setSuccessor(extendHandler); 11 12 commonHandler.handleRequest(); 13 } 14 }
5 純責任鏈與不純責任鏈
純責任鏈:
1 當handler能處理請求時,停止調用下一個handler。當handler不能處理請求時,繼續調用下一個handler。只能在兩個行為中選擇一個,一是承擔責任,二是把責任推給下家。
(好比男人要么做個有責任感的人,要么做個推卸責任的人)
2 一個請求必須被某一個處理者對象接收。
例如:工廠產品的質量檢查流水線,如果出現問題,就直接將產品拿出來。如果通過檢查,則傳遞給下一個檢查員。
不純責任鏈:
1 承擔一部分責任又把責任傳到下一個處理者(好比工廠的流水線,每處理完一道工序,交給下一個人處理)。
2 一個請求可以不被任何處理者接收。
例如:工廠產品的生產流水線,每個人都會處理一部分,然后交給下一個人。
6 優缺點
優點:
1 可以靈活方便的將處理者連接成一條鏈,滿足不同的需求。
2 將請求者與處理者解耦,提高靈活性。
缺點:
1 與if...else...缺點一樣,在找到正確邏輯處理前,要遍歷每一個邏輯判斷,當責任鏈的對象過多時,會影響性能。
7 適用環境
1 有多個對象可以處理同一請求,處理請求的時機可以放在運行時確定。
8 總結
1 責任鏈模式最大的好處:可以根據需求組織對應的責任鏈處理請求,調用某個處理者即可,不用知道它內部的實現(它可以自己處理,也可以委托其它處理者處理)。
9 問題
1 為什么不將處理器組成一個List,然后按順序處理請求?
這樣請求可能被處理多次,在某些業務場景是不合適的(比如付款單發給多個付款者,則會發生多次付款)。這些場景處理者處理完畢后,不需要下一個處理者接着處理,這樣就不能用列表,而是通過責任鏈處理,當不需要往下傳遞時,馬上終止處理。
2 責任鏈模式最可能在什么場景下使用?
當業務邏輯中包含多個if、else分支,代碼看上去很糟糕時,可以考慮使用責任鏈模式將條件判斷邏輯分散到多個處理者對象中。