【java設計模式】之 責任鏈(chain of resposibility)模式
責任鏈模式,顧名思義,就是一條鏈。這個鏈到底是怎麼執行的呢?它主要是將能夠處理同一類請求的物件連成一條鏈,所提交的請求沿著鏈傳遞,鏈上的物件逐個判斷是否有能力處理該請求,如果能則處理,如果不能則傳遞給鏈上的下一個物件進行處理,以此類推。
比如說公司請假需要審批,舉個不恰當的例子,如果請假小於3天,主管審批;3-10天的,經理審批;10-30天的,總經理審批;超過30天的,不批准等等。這就得一步步去判斷,如果撇開設計模式不看的話,那麼我們可以使用if…else…把它解決了,但是問題可想而知,實際中的複雜程度時遠遠超過這個例子的。
下面使用責任鏈模式來實現一下這個場景,先來看一下它們之間的關係結構:
Leader是個抽象類,裡面有個方法是獲取下一個Leader,Director、Manager和GeneralManager分別繼承這個抽象類。LeaveRequest中封裝了請假的相關資訊。下面來實現一下這個責任鏈模式。
首先是封裝請假資訊的類:
/**
* @Description 封裝請假的基本資訊
* @author Ni Shengwu
*
*/
public class LeaveRequest {
private String name;
private int leaveDays;
private String reason;
public LeaveRequest(String name, int leaveDays, String reason) {
super();
this.name = name;
this.leaveDays = leaveDays;
this.reason = reason;
}
//省略get和set方法
}
然後就是定義Leader這個抽象類了
/**
* @Description 領導的抽象類
* @author Ni Shengwu
*
*/
public abstract class Leader {
protected String name;
protected Leader nextLeader; //責任鏈上的後繼物件,即這個物件無法處理,就轉移給下一個Leader
public Leader(String name) {
super();
this.name = name;
}
// 設定責任鏈上的後繼物件
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
/**
* 處理請求的核心的業務方法
* 需要不同繼承該類的領導自己實現
*/
public abstract void handleRequest(LeaveRequest request);
}
主管、經理和總經理都需要繼承該類,並實現處理請假的這個方法。
/**
* @Description 主任
* @author Ni Shengwu
*
*/
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
int days = request.getLeaveDays(); //獲取請假天數
String name = request.getName(); //獲取請假人姓名
String reason = request.getReason(); // 獲取請假理由
if(days <= 3) { //如果滿足3天內的要求,主任直接審批
System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
System.out.println("主任" + this.name + "審批通過");
} else {
System.out.println("請假天數過多,主任" + this.name + "沒法處理");
if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
this.nextLeader.handleRequest(request);
}
}
}
}
/**
* @Description 經理
* @author Ni Shengwu
*
*/
public class Manager extends Leader {
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
int days = request.getLeaveDays(); //獲取請假天數
String name = request.getName(); //獲取請假人姓名
String reason = request.getReason(); // 獲取請假理由
if(days <= 10) { //如果滿足10天內的要求,經理直接審批
System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
System.out.println("經理" + this.name + "審批通過");
} else {
System.out.println("請假天數過多,經理" + this.name + "沒法處理");
if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
this.nextLeader.handleRequest(request);
}
}
}
}
/**
* @Description 總經理
* @author Ni Shengwu
*
*/
public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
int days = request.getLeaveDays(); //獲取請假天數
String name = request.getName(); //獲取請假人姓名
String reason = request.getReason(); // 獲取請假理由
if(days <= 30) { //如果滿足30天內的要求,總經理直接審批
System.out.println("員工" + name + "請假" + days + "天,理由:" + reason);
System.out.println("總經理" + this.name + "審批通過");
} else {
System.out.println("請假天數過多,總經理" + this.name + "沒法處理");
if(this.nextLeader != null) { //否則,如果鏈上存在下一個Leader,就讓他處理
this.nextLeader.handleRequest(request);
} else {
System.out.println("請假不成功");
}
}
}
}
由此可見,他們處理請求的條件是不同的,而且只要不是自己處理範圍之內的,就會將請求傳給鏈上的下一位來處理。接下來寫個客戶端模擬下:
public class Client {
public static void main(String[] args) {
Leader director = new Director("張三");
Leader manager = new Manager("李四");
Leader gManager = new GeneralManager("王五");
// 組織好責任鏈物件的關係
director.setNextLeader(manager);
manager.setNextLeader(gManager);
// 開始請假操作
LeaveRequest request = new LeaveRequest("倪升武", 15, "在家睡覺");
director.handleRequest(request);
}
}
執行結果:
請假天數過多,主任張三沒法處理
請假天數過多,經理李四沒法處理
員工倪升武請假15天,理由:在家睡覺
總經理王五審批通過
在實際中,設定這個鏈可以放到配置檔案中,可以直接修改配置檔案即可,這個責任鏈模式擴充套件性也很好,比如現在有個副經理,專門處理10-20天的請假,那麼我只要新新增一個副經理類即可,然後在責任鏈上配置一下就行了,對其他的類沒有影響。
責任鏈模式使用的地方很多,比如我們常見的try…catch…就是,可以有多個catch,一個個往下判斷;再比如servlet裡面的過濾器,就是一個責任鏈;再比如struts2中的攔截器,也是使用的責任鏈模式。
【友情提示】我的 Spring Boot 達人課上線了,您的支援是我創作的最大動力!