一、職責鏈模式異同
職責鏈模式類似於責任分配,可以讓多個對象共同參與完成某個任務,但同時也可以保證每個對象只承擔自己的任務。與常見的if…else if…else語句相比,職責鏈模式更加靈活、可擴展,並且可以方便地對代碼進行重構。
職責鏈模式的主要特點是將對象組織成一條鏈,並依次傳遞請求,每個對象負責處理自己能夠處理的請求,如果無法處理,則將請求傳遞給下一個對象處理,直至請求被處理完畢或者沒有對象可以處理為止。這種傳遞請求的方式就像一條鏈子,因此得名「職責鏈模式」。
與策略模式的區別在於:職責鏈模式強調的是對象之間的一種職責分配關係,而策略模式則強調對同一種問題採用不同的解決策略。因此,職責鏈模式更加適用於對象之間的消息傳遞與處理場景,而策略模式更加適用於演算法模塊的替換與自定義場景。
二、職責鏈模式的定義
職責鏈模式定義了一種消息傳遞機制,將多個消息處理對象組成一條鏈,依次發送消息並處理消息,達到請求者和處理者解耦的目的。職責鏈模式中通常包含以下角色:
- 抽象處理者(Handler):定義處理請求的介面,同時持有下一個處理者的引用。
- 具體處理者(ConcreteHandler):實現抽象處理者定義的介面,處理自己能夠處理的請求,如果無法處理,則將請求轉發給下一個處理者。
- 客戶端(Client):創建並組裝請求鏈的角色。
三、職責鏈模式代碼示例
// 抽象處理者 abstract class Handler { protected Handler nextHandler; public void setNextHandler(Handler handler) { this.nextHandler = handler; } public abstract void handleRequest(int request); } // 具體處理者A class ConcretHandlerA extends Handler { public void handleRequest(int request) { if (request >= 0 && request = 10 && request = 20 && request < 30) { System.out.println(this.getClass().getSimpleName() + " 處理請求 " + request); } else if (nextHandler != null) { nextHandler.handleRequest(request); } } } // 客戶端 public class Client { public static void main(String[] args) { Handler handlerA = new ConcretHandlerA(); Handler handlerB = new ConcretHandlerB(); Handler handlerC = new ConcretHandlerC(); handlerA.setNextHandler(handlerB); handlerB.setNextHandler(handlerC); // 處理請求 handlerA.handleRequest(5); handlerA.handleRequest(15); handlerA.handleRequest(25); } }
四、職責鏈模式實例
某醫院的門診醫生根據病人的病情判斷應該給予何種治療,如果是一般常見病則只需要開些簡單的藥物治療即可,如果是嚴重疾病則需要轉介至專科醫生進行診治。在這種情況下,門診醫生可以構建職責鏈對病人的病情進行判斷,並將病人轉介至相應的醫生進行診治,從而降低醫生的工作負擔並提高病人的醫療質量。
五、職責鏈模式圖片
職責鏈模式的結構就像一條鏈子,其中每個對象都持有下一個對象的引用,用於將請求傳遞給下一個對象處理。
六、職責鏈模式優缺點
職責鏈模式的優點:
- 解耦請求發送者和接收者,降低對象之間的耦合度。
- 職責鏈可以動態地組合,方便用戶自由組合職責鏈。
- 可以對請求的處理順序進行靈活配置,增加新的處理者也非常方便。
職責鏈模式的缺點:
- 請求的發起者不能確定哪個對象最終處理了請求,需要等到運行時才能確定。
- 如果職責鏈過長或者職責鏈設計不合理,可能會導致系統性能下降。
七、職責鏈模式類圖
職責鏈模式的類圖,其中抽象處理者定義了處理請求的介面,具體處理者實現了該介面並處理請求,客戶端則創建並組裝了請求處理鏈。
八、職責鏈模式結構圖
職責鏈模式的結構圖,其中每個對象都持有下一個對象的引用,用於將請求傳遞給下一個對象處理。
九、職責鏈模式實例採購單
某公司的採購員根據採購單的金額決定自己是否有許可權批准該採購單。小於等於1000元則直接批准,如果大於1000元且小於等於5000元則需要經過部門經理審批,如果大於5000元則還需要經過總經理的審批。
// 抽象處理者 abstract class Approver { protected Approver successor; //後繼處理對象 protected String name; //審批者姓名 public Approver(String name) { this.name = name; } //設置後繼者 public void setSuccessor(Approver successor) { this.successor = successor; } //抽象請求處理方法 public abstract void processRequest(PurchaseRequest request); } //具體處理者:主任類 class Director extends Approver { public Director(String name) { super(name); } public void processRequest(PurchaseRequest request) { if (request.getMoney() <= 10000) { System.out.println("主任 " + name + "審批採購單,金額為 " + request.getMoney() + " 元"); } else { successor.processRequest(request); //轉發請求 } } } //具體處理者:副董事長類 class VicePresident extends Approver { public VicePresident(String name) { super(name); } public void processRequest(PurchaseRequest request) { if (request.getMoney() <= 25000) { System.out.println("副董事長 " + name + "審批採購單,金額為 " + request.getMoney() + " 元"); } else { successor.processRequest(request); //轉發請求 } } } //具體處理者:董事長類 class President extends Approver { public President(String name) { super(name); } public void processRequest(PurchaseRequest request) { if (request.getMoney() <= 50000) { System.out.println("董事長 " + name + "審批採購單,金額為 " + request.getMoney() + " 元"); } else { System.out.println("採購單金額太大," + name + "無法處理!"); } } } //採購單類 class PurchaseRequest { private int money; //採購金額 public PurchaseRequest(int money) { this.money = money; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } } //客戶端代碼 public class Client { public static void main(String[] args) { // 先要組裝責任鏈 Approver director = new Director("張三"); Approver vp = new VicePresident("李四"); Approver president = new President("王五"); director.setSuccessor(vp); vp.setSuccessor(president); // 開始測試 PurchaseRequest request1 = new PurchaseRequest(5000); director.processRequest(request1); PurchaseRequest request2 = new PurchaseRequest(10000); director.processRequest(request2); PurchaseRequest request3 = new PurchaseRequest(30000); director.processRequest(request3); PurchaseRequest request4 = new PurchaseRequest(100000); director.processRequest(request4); } }
十、職責鏈模式實驗目的
- 學習常用的設計模式之一——職責鏈模式。
- 掌握職責鏈模式的定義、應用場景、基本結構、優缺點、類圖和實現方法。
- 通過實際代碼實現,進一步理解職責鏈模式的設計思路和使用方法。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/240861.html