责任链设计模式
概念
责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个节点都有机会(条件匹配)处理请求事务,如果某个节点处理完了就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕。
责任链模式优缺点
优点:
降低耦合度。它将请求的发送者和接收者解耦
简化了对象,使得对象不需要知道链的结构
增强给对象指派职责的灵活性,允许动态地新增或者删除责任链
增加新的请求处理类方便
缺点:
不能保证请求一定被接收;
系统性能将受到一定影响,调试时不方便,可能会造成循环调用
场景:
现实中,请假的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过滤器链等都采用了责任链设计模式。