概念
責任鏈,顧名思義,就是用來處理相關事務責任的一條執行鏈,執行鏈上有多個節點,每個節點都有機會(條件匹配)處理請求事務,如果某個節點處理完了就可以根據實際業務需求傳遞給下一個節點繼續處理或者返回處理完畢。
責任鏈模式優缺點
優點:
降低耦合度。它將請求的發送者和接收者解耦
簡化了對象,使得對象不需要知道鏈的結構
增強給對象指派職責的靈活性,允許動態地新增或者刪除責任鏈
增加新的請求處理類方便
缺點:
不能保證請求一定被接收;
系統性能將受到一定影響,調試時不方便,可能會造成循環調用
場景:
現實中,請假的OA申請,請假天數如果是半天到1天,可能直接主管批准即可;
如果是1到3天的假期,需要部門經理批准;
如果是3天到30天,則需要總經理審批;
大於30天,正常不會批准。
為了實現上述場景,我們可以采用責任鏈設計模式。
員工提交請求類:LeaveRequest。
抽象的請假責任處理類:AbstractLeaveHandler。
直接主管審批處理類:DirectLeaderLeaveHandler。
部門經理處理類:DeptManagerLeaveHandler。
總經理處理類:GManagerLeaveHandler。
員工請求發起申請到抽象的責任處理類中,根據員工的請假天數,對應的處理類完成處理。每一個責任處理類設置下面的節點。自身處理不了則傳遞給下一個節點處理。

實現
LeaveRequest.java:
1 @Setter 2 @Getter 3 @NoArgsConstructor 4 @AllArgsConstructor 5 @Builder 6 public class LeaveRequest { 7 8 /**天數*/ 9 private int leaveDays; 10 11 /**姓名*/ 12 private String name; 13 14 }
AbstractLeaveHandler.java
1 /** 2 * @Author: guodong 3 * @Date: 2021/2/22 16:00 4 * @Version: 1.0 5 * @Description: 請假責任鏈抽象處理類 6 */ 7 public class AbstractLeaveHandler { 8 9 /**直接主管審批處理的請假天數*/ 10 protected int MIN = 1; 11 /**部門經理處理的請假天數*/ 12 protected int MIDDLE = 3; 13 /**總經理處理的請假天數*/ 14 protected int MAX = 30; 15 16 /**領導名稱*/ 17 protected String handlerName; 18 19 /**下一個處理節點(即更高級別的領導)*/ 20 protected AbstractLeaveHandler nextHandler; 21 22 /**設置下一節點*/ 23 protected void setNextHandler(AbstractLeaveHandler handler){ 24 this.nextHandler = handler; 25 } 26 27 /**處理請假的請求,子類實現*/ 28 protected void handlerRequest(LeaveRequest request){ 29 30 } 31 32 }
DirectLeaderLeaveHandler.java
1 /** 2 * @Author: guodong 3 * @Date: 2021/2/22 16:03 4 * @Version: 1.0 5 * @Description: 直接主管處理類 6 */ 7 public class DirectLeaderLeaveHandler extends AbstractLeaveHandler{ 8 9 public DirectLeaderLeaveHandler(String name) { 10 this.handlerName = name; 11 } 12 13 @Override 14 protected void handlerRequest(LeaveRequest request) { 15 if(request.getLeaveDays() <= this.MIN){ 16 System.out.println("直接主管:" + handlerName + ",已經處理;流程結束。"); 17 return; 18 } 19 20 if(null != this.nextHandler){ 21 this.nextHandler.handlerRequest(request); 22 }else{ 23 System.out.println("審批拒絕!"); 24 } 25 } 26 27 }
DeptManagerLeaveHandler.java
1 /** 2 * @Author: guodong 3 * @Date: 2021/2/22 16:05 4 * @Version: 1.0 5 * @Description: 部門經理處理類 6 */ 7 public class DeptManagerLeaveHandler extends AbstractLeaveHandler { 8 9 public DeptManagerLeaveHandler(String name) { 10 this.handlerName = name; 11 } 12 13 @Override 14 protected void handlerRequest(LeaveRequest request) { 15 if(request.getLeaveDays() >this.MIN && request.getLeaveDays() <= this.MIDDLE){ 16 System.out.println("部門經理:" + handlerName + ",已經處理;流程結束。"); 17 return; 18 } 19 20 if(null != this.nextHandler){ 21 this.nextHandler.handlerRequest(request); 22 }else{ 23 System.out.println("審批拒絕!"); 24 } 25 } 26 27 }
GManagerLeaveHandler.java
1 /** 2 * @Author: guodong 3 * @Date: 2021/2/22 16:06 4 * @Version: 1.0 5 * @Description: 總經理處理類 6 */ 7 public class GManagerLeaveHandler extends AbstractLeaveHandler { 8 9 public GManagerLeaveHandler(String name) { 10 this.handlerName = name; 11 } 12 13 @Override 14 protected void handlerRequest(LeaveRequest request) { 15 if(request.getLeaveDays() > this.MIDDLE && request.getLeaveDays() <= this.MAX){ 16 System.out.println("總經理:" + handlerName + ",已經處理;流程結束。"); 17 return; 18 } 19 20 if(null != this.nextHandler){ 21 this.nextHandler.handlerRequest(request); 22 }else{ 23 System.out.println("審批拒絕!"); 24 } 25 } 26 27 }
ResponsibilityTest.java
1 public class ResponsibilityTest { 2 3 public static void main(String[] args) { 4 LeaveRequest request = LeaveRequest.builder().leaveDays(20).name("小明").build(); 5 6 AbstractLeaveHandler directLeaderLeaveHandler = new DirectLeaderLeaveHandler("縣令"); 7 DeptManagerLeaveHandler deptManagerLeaveHandler = new DeptManagerLeaveHandler("知府"); 8 GManagerLeaveHandler gManagerLeaveHandler = new GManagerLeaveHandler("京兆尹"); 9 10 directLeaderLeaveHandler.setNextHandler(deptManagerLeaveHandler); 11 deptManagerLeaveHandler.setNextHandler(gManagerLeaveHandler); 12 13 directLeaderLeaveHandler.handlerRequest(request); 14 } 15 16 }
- 20天,運行輸出: 總經理:京兆尹,已經處理;流程結束。
- 1天,運行輸出: 直接主管:縣令,已經處理;流程結束。
- 3天,運行輸出: 部門經理:知府,已經處理;流程結束。
- 35天,運行輸出: 審批拒絕!
總結
責任鏈主要重在責任分離處理,讓各個節點各司其職。
責任鏈上的各個節點都有機會處理事務,但是也可能不會受理請求。
責任鏈比較長,調試時可能會比較麻煩。
責任鏈一般用於處理流程節點之類的實際業務場景中。
Spring攔截器鏈、servlet過濾器鏈等都采用了責任鏈設計模式。
