職責鏈模式 定義 使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這個對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。 UML圖 好處 當客戶提交一個請求時,請求是沿鏈傳遞直至有一個 ConcreteHandler 對象負責處理它 接收者和發送者都沒有對方 ...
職責鏈模式
定義
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關係。將這個對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
UML圖
好處
- 當客戶提交一個請求時,請求是沿鏈傳遞直至有一個 ConcreteHandler 對象負責處理它
- 接收者和發送者都沒有對方的明確信息,且鏈中對象自己也並不知道鏈的結構。結果時職責鏈可簡化對象的相互連接,它們僅需保持一個指向其後繼者的引用,而不需要保持他所有的候選者接收者的引用。
- 可以隨時的增加或修改一個請求的結構,增強給對象指派職責的靈活性
但需要註意的是:一個請求極有可能到了鏈的末端都得不到處理,或者因為沒有正確配置而得不到處理。
舉個慄子
員工申請加薪,需要走流程
Talk is cheap, show me the code
(屁話少說,放碼過來)
/**
* 管理者
* Created by callmeDevil on 2019/12/14.
*/
public abstract class Manager {
protected String name;
// 上級
protected Manager superior;
public Manager(String name){
this.name = name;
}
// 設置上級
public void setSuperior(Manager superior){
this.superior = superior;
}
// 申請請求
public abstract void requestApplications(Request request);
}
/**
* 經理
* Created by callmeDevil on 2019/12/14.
*/
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
// 經理的許可權可以批准2天內的假期
if ("請假".equals(request.getRequestType()) && request.getNumber() <= 2) {
System.out.println(String.format("%s : %s 數量%s 被批准", name, request.getRequestContent(), request.getNumber()));
} else {
// 其餘申請轉交上級
if (superior != null) {
superior.requestApplications(request);
}
}
}
}
/**
* 總監
* Created by callmeDevil on 2019/12/14.
*/
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
// 總監的許可權可以批准5天內的假期
if ("請假".equals(request.getRequestType()) && request.getNumber() <= 5) {
System.out.println(String.format("%s : %s 數量%s 被批准", name, request.getRequestContent(), request.getNumber()));
} else {
// 其餘申請轉交上級
if (superior != null) {
superior.requestApplications(request);
}
}
}
}
/**
* 總經理
* Created by callmeDevil on 2019/12/14.
*/
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void requestApplications(Request request) {
// 總經理可以批准任意天的假期
if ("請假".equals(request.getRequestType())) {
System.out.println(String.format("%s : %s 數量%s 被批准", name, request.getRequestContent(), request.getNumber()));
}
// 加薪在500內,沒問題
else if ("加薪".equals(request.getRequestType()) && request.getNumber() <= 500) {
System.out.println(String.format("%s : %s 數量%s 被批准", name, request.getRequestContent(), request.getNumber()));
}
// 加薪超過500要考慮一下
else if ("加薪".equals(request.getRequestType()) && request.getNumber() > 500) {
System.out.println(String.format("%s : %s 數量%s 再說吧", name, request.getRequestContent(), request.getNumber()));
}
}
}
/**
* 申請類
* Created by callmeDevil on 2019/12/14.
*/
public class Request {
// 申請級別
private String requestType;
// 申請內容
private String requestContent;
// 數量
private int number;
// 省略get set
}
public class Test {
public static void main(String[] args) {
CommonManager commonManager = new CommonManager("中將");
Majordomo majordomo = new Majordomo("大將");
GeneralManager generalManager = new GeneralManager("元帥");
// 設置上級
commonManager.setSuperior(majordomo);
majordomo.setSuperior(generalManager);
Request request = new Request();
request.setRequestType("請假");
request.setRequestContent("不給請假我不幹了");
request.setNumber(1);
commonManager.requestApplications(request); // 客戶端的申請都是由經理髮起的,但實際上決策是誰,客戶端不知道
Request request2 = new Request();
request2.setRequestType("請假");
request2.setRequestContent("不給請假我不幹了");
request2.setNumber(4);
commonManager.requestApplications(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("不給加薪我不幹了");
request3.setNumber(500);
commonManager.requestApplications(request3);
Request request4 = new Request();
request4.setRequestType("加薪");
request4.setRequestContent("不給加薪我不幹了");
request4.setNumber(1000);
commonManager.requestApplications(request4);
}
}
運行結果
中將 : 不給請假我不幹了 數量1 被批准
大將 : 不給請假我不幹了 數量4 被批准
元帥 : 不給加薪我不幹了 數量500 被批准
元帥 : 不給加薪我不幹了 數量1000 再說吧