設計模式之——責任鏈設計模式
阿新 • • 發佈:2019-02-02
通常每個接收者都包含對另一個接收者的引用。如果一個物件不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。
該模式在生活中很常見,比如:汽車製造、物流分揀、食品加工、質量檢測等等,生活中更多的是這樣的非純責任模式,也就是說,每個節點都會根據自己的職責操作自己對應的部分,然後轉交下一節點處理;也有純責任模式,比如質檢,一旦某個節點出問題直接不合格並打回。這種模式一般是從低等級往高等級層層請求。
我們來舉個團建經費申請的例子:
場景設定:
專案經理(500) - 部門主管(1000) - 總經理(2000) - 老闆(2000~5000)
首先抽象出經理,並建立鏈的連線關係
package com.zndroid.dm.ChainOfResponseModel; /** * Created by luzhenyu on 2017/9/18. */ /**抽象出可處理的物件,並提供‘鏈’的關聯和具體類的處理請求*/ public abstract class Manager { public abstract void request(int mount);//請求入口 public void setNextManager(Manager nextManager) { this.nextManager = nextManager; } protected Manager nextManager;//提供鏈關聯 public void done() { System.out.println("[OK...]"); } }
具體節點
package com.zndroid.dm.ChainOfResponseModel.impl; import com.zndroid.dm.ChainOfResponseModel.Manager; /** * Created by luzhenyu on 2017/9/18. */ public class ProjectManager extends Manager { @Override public void request(int mount) { if (mount <= 500) { System.out.println("專案經理審批通過,申請金額:" + mount); done(); return; } else { System.out.println("金額超出專案經理的範圍,開始轉交上級處理..."); nextManager.request(mount); } } }
package com.zndroid.dm.ChainOfResponseModel.impl; import com.zndroid.dm.ChainOfResponseModel.Manager; /** * Created by luzhenyu on 2017/9/18. */ public class DepartmentManager extends Manager { @Override public void request(int mount) { if (mount > 500 && mount <= 1000) { System.out.println("部門主管審批通過,申請金額:" + mount); done(); return; } else { System.out.println("金額超出部門主管的範圍,開始轉交上級處理..."); nextManager.request(mount); } } }
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class GeneralManager extends Manager {
@Override
public void request(int mount) {
if (mount > 1000 && mount <= 2000) {
System.out.println("總經理審批通過,申請金額:" + mount);
done();
return;
}
else {
System.out.println("金額超出總經理的範圍,開始轉交上級處理...");
nextManager.request(mount);
}
}
}
package com.zndroid.dm.ChainOfResponseModel.impl;
import com.zndroid.dm.ChainOfResponseModel.Manager;
/**
* Created by luzhenyu on 2017/9/18.
*/
public class BossManager extends Manager {
@Override
public void request(int mount) {
if (mount > 2000 && mount <= 5000) {
System.out.println("老闆審批通過,申請金額:" + mount);
done();
return;
}
else {
System.out.println("老闆哭窮中...");
}
}
}
使用如下/**
* 職責鏈模式
* 使多個物件都有可能處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這個物件連成一條鏈,並沿著這條鏈傳遞請求,直到有一個物件處理它為止。
*
* 往往它是一個從最低階到上層的請求方式,職責鏈模式可以靈活的改變內部的傳遞規則,每個人可以動態的制定自己的繼承者。
* 如果初始層級暫時不在或消失,請求也可以直接傳送給其他層級,後續職責鏈還會繼續進行。而且可以隨時增加和修改處理一個請求的結構,增加了給物件指派的職責的靈活性。
*
* 優點:
* 呼叫者不需知道具體誰來處理請求,也不知道鏈的具體結構,降低了節點域節點的耦合度;可在執行時動態修改鏈中的物件職責,增強了給物件指派職責的靈活性;
* 缺點:
* 沒有明確的接收者,可能傳到鏈的最後,也沒得到正確的處理;系統性能會受到影響;程式碼除錯比較繁瑣。
*
* 具體應用:
* OA系統;在java中的實際應用有Servlet中的過濾器(Filter);Struts2的攔截器(Interceptor),生活中大部分流程還是不純的責任鏈,也就是每個節點的物件都有可能
* 做了對應的操作,高層次的操作要以低層次的為依據,比如:公司請假肯定要部門經理先同意才能走到下一級,而不是說,部門經理不同意就會走到老闆那。
* */
//下面來模擬一下公司的團建申請
//比方說現在有三個老總可以處理團建申請,他們的可以批示的金額分變為:
//專案經理(500) - 部門主管(1000) - 總經理(2000) - 老闆(2000~5000)
//建立節點:
ProjectManager projectManager = new ProjectManager();
DepartmentManager departmentManager = new DepartmentManager();
com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager generalManager= new com.zndroid.dm.ChainOfResponseModel.impl.GeneralManager();
BossManager bossManager = new BossManager();
//建立連結:
projectManager.setNextManager(departmentManager);
departmentManager.setNextManager(generalManager);
generalManager.setNextManager(bossManager);
projectManager.request(3000);
log("----------------我是分割線-----------------");
執行結果:
[ ======================================== ]
金額超出專案經理的範圍,開始轉交上級處理...
金額超出部門主管的範圍,開始轉交上級處理...
金額超出總經理的範圍,開始轉交上級處理...
老闆審批通過,申請金額:3000
[OK...]
[ ----------------我是分割線----------------- ]
[ ======================================== ]
【歡迎上碼】
【微信公眾號搜尋 h2o2s2】