責任鏈模式是一種行為型模式,將一系列處理者鏈接在一起,形成一個處理整體,將具體的請求處理者與請求者進行分離,本文介紹了職責鏈模式的意圖,使用場景,以及結構,角色模塊,並且給出來了Java版本的責任鏈模式實現。 ...
責任鏈模式(Chain of Responsibility Pattern) 職責鏈模式
![image_5c0e046c_2968 image_5c0e046c_2968](https://img2018.cnblogs.com/blog/897393/201812/897393-20181210141909383-1923784040.png)
意圖
使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係 將這些對象連接成一條鏈,並沿著這條鏈傳遞請求,直到有一個對象處理它為止。 責任鏈模式中,每個對象通過持有對下家的引用而鏈接起來,形成一條鏈條,串聯起來多個處理對象。 在責任鏈模式中,請求在鏈上進行傳遞,直到鏈上的某一個對象決定處理此請求。 發出這個請求的客戶端程式並不知道到底是哪一個對象具體的處理了請求 這使得系統可以在不影響客戶端的情況下,動態的重新組織鏈和增加責任 比如類載入機制中的雙親委派模型,類載入器含有父 類載入器的引用,形成了一個處理鏈 (不過類載入機制的具體行為與責任鏈有出入,會一直委派到最頂級類載入,而不會在中間進行處理然後返回)解析
責任鏈模式是一種很常見的場景 比如請假,很多公司會根據請假的原因以及請假的時長,將會有不同的審批人 比如採購,對於採購金額的不同,可能需要不同的審批人 思考下請假的過程,可能你經歷過有兩種形式: 形式一: 第一步你寫好請假條;第二步你拿給人事,人事說找部門主管簽字
第三步你拿請假條給部門主管,部門主管發現請假三天,然後告訴你,一天以上的假期需要老闆審批
第四步你拿請假條給老闆審批 形式二: 第一步你寫好請假條交給人事;(人事拿給部門主管,部門主管看情況,如果批不了拿給老闆審批) 第二步等待審批; 可能的兩種流程就是上面這樣子的,請假的流程一般就這樣子了,總共有幾級審批,這幾級審批都有誰負責,也不會輕易的變化 再看一個採購審批的例子 示例 以採購為例演示審批流程 抽象處理人角色 處理人擁有姓名屬性,另外定義了抽象的操作方法
package nonechainresponsibility; public abstract class Handler { protected String name; Handler(String name){ this.name = name; } public abstract void operation(); }
具體的處理人角色 DepartmentManager和Boss
package nonechainresponsibility; public class DepartmentManager extends Handler { public DepartmentManager(String name){ super(name); } @Override public void operation() { System.out.println("DepartmentManager process..name: "+this.name); } }
package nonechainresponsibility; public class Boss extends Handler { public Boss(String name) { super(name); } @Override public void operation() { System.out.println("Boss process..name: " + this.name); } }測試代碼如下,流程很簡單: 如果是金額小於1000元,由部門經理DepartmentManager 李四審批 否則,將由老總 Boss 張三 審批
![image_5c0e046c_6677 image_5c0e046c_6677](https://img2018.cnblogs.com/blog/897393/201812/897393-20181210141910210-122440304.png)
代碼示例
處理人角色新增successor 屬性,用於作為下游處理,提供了setSuccessor()方法進行設置 並且對operation方法進行改變,接受參數(Integer price)package chainresponsibility; public abstract class Handler { protected String name; Handler(String name){ this.name = name; } protected Handler successor; public void setSuccessor(Handler successor){ this.successor = successor; } public abstract void operation(Integer price); }部門處理人角色和老闆角色同步做出修改 將判斷邏輯移入到處理內部 如果自己不能處理,那麼請求下游進行處理(示例比較簡單,所以Boss沒搞)
package chainresponsibility; public class DepartmentManager extends Handler { public DepartmentManager(String name){ super(name); } @Override public void operation(Integer price) { if(price < 1000){ System.out.println("DepartmentManager process..name: "+this.name); }else{ successor.operation(price); } } }
package chainresponsibility; public class Boss extends Handler { public Boss(String name) { super(name); } @Override public void operation(Integer price) { System.out.println("Boss process..name: " + this.name); } }測試代碼
package chainresponsibility; public class Test { public static void main(String[] args){ /* * 動態生成鏈條 * */ Handler DmHandler = new DepartmentManager("李四"); Handler BossHandler = new Boss("張三"); DmHandler.setSuccessor(BossHandler); /* * 調用處理鏈的一個起始端點 * */ DmHandler.operation(600); DmHandler.operation(6000); } }
![image_5c0e046c_872 image_5c0e046c_872](https://img2018.cnblogs.com/blog/897393/201812/897393-20181210141911062-1779158432.png)
結構
![image_5c0e046c_6dbf image_5c0e046c_6dbf](https://img2018.cnblogs.com/blog/897393/201812/897393-20181210141912244-1167212334.png)
Client角色向組裝好的責任鏈的第一個ConcreteHandler發起請求
通過責任鏈模式弱化了請求發起者與請求處理者的聯繫 對於請求者來說,責任鏈上的所有對象就是一個請求處理者,到底具體到哪個類進行出力,請求者並不關心 不存在“某個請求必須要誰處理”這種明確的指向關係,請求者不清楚 專註於自己的工作 每個處理業務的對象都更加專註於自己的工作,如果自己無法處理,那麼交給其他更專業的人 這樣則能保障任務能夠快速高效的完成 責任鏈模式並不創建責任鏈,由系統的其他部分負責創建 示例為了簡單所以在測試主函數中一併創建,應該由系統其他部分進行創建,將責任鏈的連接邏輯與使用解耦 動態改變職責鏈 引用是組合的形式,可以在運行時動態的設定 上面說到責任鏈由系統的其他部分進行創建,他可以動態的完成責任鏈的創建
分類
責任鏈模式分為純粹的責任鏈模式和不純粹的責任鏈模式 純粹的責任鏈模式要求責任鏈中的對象,也就是具體的處理者只能在兩個行為中選擇一個 也就是要麼承擔責任,要麼責任轉交給下家 不允許出現某一個具體的處理者對象承擔了一部分責任之後又把責任向下傳遞。 而通常情況下,我們的實際使用的責任鏈模式很難純粹,基本都會摻雜一些處理邏輯 其實這種命名與否的爭論對於使用模式毫無意義,重點在於解決問題 黑貓白貓抓到老鼠就是好貓總結
如果你的系統中已經存在了一個由多個處理者對象組成的請求處理序列 那麼你就可以考慮將這個請求處理轉換為責任鏈模式 如果有多於一個處理者對象會處理一個請求,但是事先卻並不知道到底誰來處理 這個處理者對象是動態確定的,比如新來一個採購員,他還不熟悉公司規則,不確定到底誰來負責審批他的這個單子 責任鏈顯著的特點就是將請求和處理者進行分離,請求者可以不知道具體是誰處理了請求,將請求與處理進行瞭解耦,提高了系統的靈活性 具體的處理者可能還與責任鏈的組成順序有很大的關係,通過選擇某些處理者組成鏈,以及設置順序,增加了極大的靈活性 責任鏈模式所有的請求都通過責任鏈進行處理,如果鏈比較長,而且需求總是在後端進行處理,勢必會引入一些性能問題 而且,客戶端不知道具體誰處理的,你也不知道,環節較多,調試時也會不方便 而且還需要控制節點的數量,要避免超長鏈的情況,那樣這條鏈將會變成一種負擔,這種會破壞系統的性能 而且還需要註意,如果一個請求從頭走到尾是否一定會有對象對他進行處理?如果沒有被處理也可能是因為沒有正確的配置責任鏈而導致的 如果鏈接生成的有問題,比如環形,並且也沒有設置次數限制,豈不是死迴圈?這些問題都需要在運用時考慮到 對於責任鏈一句話總結:如果一個請求,可能會被多個處理者中的一個處理,考慮責任鏈模式 原文地址:責任鏈模式 職責鏈模式 Chain of Responsibility Pattern 行為型 設計模式(十七)