Java-責任鏈-設計模式(十六)
阿新 • • 發佈:2021-01-28
說明
責任鏈模式(Chain of Responsibility)使多個物件都有機會處理請求,從而避免請求的傳送者和接收者之間的耦合關係。將這個物件連城一條鏈,並沿著這條鏈傳遞請求,直到有一個物件處理它為止。
角色:
抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義 出一個方法以設定和返回對下家的引用。這個角色通常由一個Java抽象類或者Java介面實現。Handler類的聚合關係給出了具體子類對下家的引用,抽象方法handleRequest()規範了子類處理請求的操作。
具體處理者(ConcreteHandler)角色
程式碼
以張三發起一個請假或加薪的申請為例,審批人有主管,總監,總經理,各自許可權不同。
主管:只能處理兩天以內的請假請求,其餘的轉交給上級。
總監:許可一週以內的請假,其餘轉交給上級。
總經理:所有請假都批准;500以內加薪批准,超出500需要考慮。
此例參考《大話設計模式》,程式碼如下。
抽象處理者角色
/**
* @author ctl
* @date 2021/1/27
* 管理者
*/
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 request(Request request);
}
具體處理者角色,主管
/**
* @author ctl
* @date 2021/1/27
* 主管
* 許可權:只能處理兩天以內的請假請求,其餘的轉交給上級
*/
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void request(Request request) {
if ("請假".equals(request.getRequestType()) && request.getNum() <= 2) {
System.out.println(name + ":" +
request.getRequestContent() +
" 數量" + request.getNum() + " 被批准");
} else {
// 轉交上級
if (superior != null) {
superior.request(request);
}
}
}
}
具體處理者角色,總監
/**
* @author ctl
* @date 2021/1/27
* 總監
* 許可權:許可一週以內的請假
*/
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void request(Request request) {
if ("請假".equals(request.getRequestType()) && request.getNum() <= 5) {
System.out.println(name + ":" +
request.getRequestContent() +
" 數量" + request.getNum() + " 被批准");
} else {
// 轉交上級
if (superior != null) {
superior.request(request);
}
}
}
}
具體處理者角色,總經理
/**
* @author ctl
* @date 2021/1/27
* 總經理
* 許可權:最高階,所有型別的請求都處理
* 請假都批
* 加薪500以下批,否則需要考慮
*/
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void request(Request request) {
// 請假 都批准
if ("請假".equals(request.getRequestType())) {
System.out.println(name + ":" +
request.getRequestContent() +
" 數量" + request.getNum() + " 被批准");
} else if ("加薪".equals(request.getRequestType()) && request.getNum() <= 500) {
// 加薪 500以下批准 超過500 考慮考慮
System.out.println(name + ":" +
request.getRequestContent() +
" 數量" + request.getNum() + " 被批准");
} else if ("加薪".equals(request.getRequestType()) && request.getNum() > 500) {
System.out.println(name + ":" +
request.getRequestContent() +
" 數量" + request.getNum() + " 需要考慮考慮");
}
}
}
申請物件,封裝了申請內容
/**
* @author ctl
* @date 2021/1/27
* 申請物件
*/
public class Request {
// 申請型別
private String requestType;
// 申請內容
private String requestContent;
// 申請數量
private int num;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public String getRequestContent() {
return requestContent;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
測試類
/**
* @author ctl
* @date 2021/1/27
*/
public class ChainMain {
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.setNum(1);
commonManager.request(request);
Request request2 = new Request();
request2.setRequestType("請假");
request2.setRequestContent("張三請假");
request2.setNum(4);
commonManager.request(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("張三請求加薪");
request3.setNum(500);
commonManager.request(request3);
Request request4 = new Request();
request4.setRequestType("加薪");
request4.setRequestContent("張三請求加薪");
request4.setNum(1000);
commonManager.request(request4);
}
}
結果
張三發起申請,只對接主管,最終根據設定的級別許可權,所有角色進行了對應的審批。
總結
責任鏈模式的好處就是接收者和傳送者彼此都不知道對方的角色,而且鏈中的物件自己也不知道鏈的結構。大大降低了耦合度。並且可以隨時按需修改處理一個請求的結構,增強了給物件指派指責的靈活性。