責任鏈模式(Chain Of Responsibility)
Chain Of Responsibility?
這種情況下,我們可以考慮將多個物件組成一條職責鏈,然後按照它們在職責鏈上的順序一個一個地找出到底應該誰來負責處理。
通俗:她告訴我們應該去“營業視窗”。然後等我們到了“營業視窗”後,又被告知應該去“售後部門”。等我們好不容易趕到了“售後部門”,又被告知應該去“資料中心”,因此最後我們又不得不趕往“資料中心”。像這樣,在找到合適的辦事人之前,我們被不斷地踢給一個又一個人,這就是“推卸責任”。
理解職責
-
理解好責任鏈設計模式關鍵在於 SolveAnswer是處理者而NoSolve、LimitSolve、OddSolve、SpcialSolve才是具體的處理者。
在SolveAnswer用模版設計的模式定義遇到解決問題的策略辦法,能解決就在當前實現的解決方法的子類進行解決,不能解決就在繼續向下面的責任類繼續傳遞。
-
|名字 +++++++++++++++++++++++++++++++說明
|Question|表示發生的問題的類。它帶有問題編號(number)
SolveAnswer用來解決問題的抽象類
NoSolve用來解決問題的具體類(永遠“不處理問題”)
LimitSolve用來解決問題的具體類(僅解決編號小於指定編號的問題)
OddSolve|用來解決問題的具體類(僅解決奇數編號的問題)
SpcialSolve用來解決問題的具體類(僅解決指定編號的問題)
MainT 製作SolveAnswer的職責鏈,製造問題並測試程式行為
-
比較重要的話:
Chain of Responsibility模式的最大優點就在於它弱化了發出請求的人(Client角色)和處理請求的人(ConcreteHandler角色)之間的關係。Client角色向第一個ConcreteHandler角色發出請求,然後請求會在職責鏈中傳播,直到某個ConcreteHandler角色處理該請求。
如果不使用該模式,就必須有某個偉大的角色知道“誰應該處理什麼請求”,這有點類似中央集權制。而讓“發出請求的人”知道“誰應該處理該請求”並不明智,因為如果發出請求的人不得不知道處理請求的人各自的責任分擔情況,就會降低其作為可複用的元件的獨立性。
-
需要知道的技術點:
使用Chain of Responsibility模式可以推卸請求,直至找到合適的處理請求的物件,這樣確實提高了程式的靈活性,但是會有一定的處理延遲:當然你也可以通過演算法來定義處理的特殊路徑,但是未免太多餘麻煩:所以有的時候我們不如直接顯示呼叫來提高靈活性。
UML
時序圖:
Code
- Question :
public class Question { private int question_number; public Question(int question_number) { this.question_number = question_number; } public int getQuestion_number() { return question_number; } @Override public String toString() { return "Question{" + "question_number=" + question_number + '}'; } }
- SolveAnswer
public abstract class SolveAnswer { private String Solve_Name; // 繼承鏈者 private SolveAnswer next; public SolveAnswer(String solve_Name) { Solve_Name = solve_Name; } /** * 設定需要推卸責任的物件 */ public SolveAnswer setNext(SolveAnswer solveAnswer){ this.next=solveAnswer; return next; } /** * 解決問題的步驟 */ public final void support(Question question){ if(solve(question)){ finish(question); }else if(next!=null){ this.next.support(question); }else{ fail(question); } } /** * 交給子類取解決 * @param question * @return */ protected abstract boolean solve(Question question); /** * * @param question */ private void finish(Question question) { System.out.println(question+"能被解決"+this.toString()+"."); } /** * * @param question */ private void fail(Question question) { System.out.println(question+"不能被解決."); } @Override public String toString() { return "["+this.Solve_Name+ "]"; } }
- NoSolve SpcialSolve OddSolve LimitSolve
public class LimitSolve extends SolveAnswer { private int limit; public LimitSolve(String solve_Name ,int limit) { super(solve_Name); this.limit=limit; } @Override public boolean solve(Question question) { if(question.getQuestion_number()<limit){ return true; }else{ return false; } } } public class NoSolve extends SolveAnswer{ public NoSolve(String solve_Name) { super(solve_Name); } @Override public boolean solve(Question question) { return false; } } public class OddSolve extends SolveAnswer { public OddSolve(String solve_Name) { super(solve_Name); } @Override public boolean solve(Question question) { if(question.getQuestion_number()%2==1){ returntrue; }else{ return false; } } } public class SpcialSolve extends SolveAnswer { private int special; public SpcialSolve(String solve_Name,int specalNum) { super(solve_Name); this.special=specalNum; } @Override public boolean solve(Question question) { if(question.getQuestion_number()==special){ return true; }else { return false; } } }
- MainT 測試
public class MainT { public static void main(String[] args) { SolveAnswer tom=new NoSolve("cat1"); SolveAnswer tom2=new LimitSolve("cat2",100); SolveAnswer tom3=new OddSolve("cat3"); //只能解決225問題 SolveAnswer tom4=new SpcialSolve("cat4",225); tom.setNext(tom2).setNext(tom3).setNext(tom4); for (int i = 0; i < 300; i+=3) { tom.support(new Question(i)); } } }