👉 文章示例代码 👈
定义
使多个对象都有机会去处理请求。从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
责任链模式也叫做职责链模式 。
三个角色 责任链模式主要有以下三个角色:
抽象处理者Handler :定义一个处理请求的接口,内部包含一个后继处理者的引用。
具体处理者Concrete Handler :实现抽象处理者。如果能够处理请求则处理,否则就将该请求转发给它的后继处理者。
客户端类Client :创建处理链,同时向链头的具体处理者对象提交请求,它并不关心处理细节和请求的传递过程。
场景示例 现在多数公司请假都通过钉钉来走审批流程,不同的公司审批的规则也不同。
笔者这里以请事假为例,以及以下审批事假规则来简单讲解责任链模式。
事假天数(最小单位:天)
审批人
1天
组长->人事经理
1天-7天(包含7天)
组长->总监->人事经理
7天以上
组长->总监->老板->人事经理
创建请求实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class PersonalLeaveRequest { private String applicant; private Integer days; private String startTime; private String reason; public interface Days { Integer ONE = 1 ; Integer SEVEN = 7 ; } }
创建抽象处理者 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public abstract class Approver { protected Approver approver; public void setNextApprpver (Approver approver) { this .approver = approver; } public abstract void approve (PersonalLeaveRequest request) ; }
创建具体处理者 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 public class BossApprover extends Approver { @Override public void approve (PersonalLeaveRequest request) { if (StringUtils.isNotEmpty(request.getReason())) { System.out.println("老板审核结果: 批准" ); if (approver != null ) { approver.approve(request); } } else { System.out.println("老板审核结果: 不批准" ); } } } public class InspectorGeneralApprover extends Approver { @Override public void approve (PersonalLeaveRequest request) { if (StringUtils.isNotEmpty(request.getReason())) { System.out.println("总监审核结果: 批准" ); if (approver != null ) { approver.approve(request); } } else { System.out.println("总监审核结果: 不批准" ); } } } public class GroupLeaderApprover extends Approver { @Override public void approve (PersonalLeaveRequest request) { if (StringUtils.isNotEmpty(request.getReason())) { System.out.println("组长审核结果: 批准" ); if (approver != null ) { approver.approve(request); } } else { System.out.println("组长审核结果: 不批准" ); } } } public class PersonnelManagerApprover extends Approver { @Override public void approve (PersonalLeaveRequest request) { if (StringUtils.isNotEmpty(request.getReason())) { System.out.println("人事经理审核结果: 批准" ); if (approver != null ) { approver.approve(request); } } else { System.out.println("人事经理审核结果: 不批准" ); } } }
这里需要注意一下,在每个具体的处理类当中 if (approver != null) {}
这个判断是否存在后继处理者引用的分支是必须存在的。
测试类及输出 这里的测试类也可以作为我们的客户端类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 public class Test { public static void main (String[] args) { PersonalLeaveRequest request = new PersonalLeaveRequest(); request.setApplicant("海豪" ); request.setDays(6 ); request.setStartTime("2020年03月03日15:24:37" ); request.setReason("家中有事" ); Approver groupLeaderApprover = new GroupLeaderApprover(); Approver personnelManagerApprover = new PersonnelManagerApprover(); Approver inspectorGeneralApprover = new InspectorGeneralApprover(); Approver bossApprover = new BossApprover(); Integer days = request.getDays(); if (PersonalLeaveRequest.Days.ONE.equals(days)) { groupLeaderApprover.setNextApprpver(personnelManagerApprover); } else if (days > PersonalLeaveRequest.Days.ONE && days <= PersonalLeaveRequest.Days.SEVEN) { groupLeaderApprover.setNextApprpver(inspectorGeneralApprover); inspectorGeneralApprover.setNextApprpver(personnelManagerApprover); } else if (days > PersonalLeaveRequest.Days.SEVEN) { groupLeaderApprover.setNextApprpver(inspectorGeneralApprover); groupLeaderApprover.setNextApprpver(bossApprover); bossApprover.setNextApprpver(personnelManagerApprover); } else { throw new RuntimeException("请假天数异常" ); } System.out.println(">>>>" ); System.out.println( String.format("[%s]发起请假申请, 请假天数[%s]天, 请假开始时间[%s], 请假理由[%s]" , request.getApplicant(), request.getDays(), request.getStartTime(), request.getReason())); System.out.println("<<<<" ); System.out.println("审核结果如下:" ); groupLeaderApprover.approve(request); } }
测试类的输出结果如下:
>>>> [海豪]发起请假申请, 请假天数[6]天, 请假开始时间[2020年03月03日15:24:37], 请假理由[家中有事] <<<< 审核结果如下: 组长审核结果: 批准 总监审核结果: 批准 人事经理审核结果: 批准
类结构图 以上示例类的结构图如下所示
总结 适用场景 一个请求的处理需要多个对象当中的一个或者几个协作处理。
优点
降低对象之间的耦合度。对请求的发送者和接收者进行解耦。
责任链可以动态组合。当工作流程发生变化时,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
缺点
责任链较长时,请求的处理可能会涉及多个对象,从而影响系统的性能。
参考