文章内容
一、什么是责任链模式
责任链模式,为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一个对象记住下一个对象的引用,而成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
责任链模式,也叫职责链模式,属于行为型设计模式。
二、责任链模式类图

三、责任链模式角色
- 抽象处理者角色(Handler):定义一个处理请求的接口,包含抽象处理方法和一个后续连接。
- 具体处理者角色(ConcreteHandler):实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理则处理,否则该请求转给它的后继者。
四、责任链模式优缺点
1、优点
- 降低了请求者和接受者对象之间的耦合度。
- 增强了系统的可扩展性,新增处理类时,满足开闭原则。
- 增强了给对象指派职责的灵活性:当流程工作发生变化时,可以根据需要动态调整责任链的顺序,也可新增或删除责任链。
- 责任链简化了对象之间的连接:一个责任链只需保持一个其后继者的引用,无需保持其它处理者的引用。
- 责任链分工明确:每个责任链只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,满足单一职责原则
2、缺点
- 不能保证每个请求都能被处理。
- 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能由于责任链的错误设置而导致系统出错。
五、责任链模式demo示例
1、Demo需求
以请假审批流程为例,公司员工请假审批流程是:员工请假天数小于3天,小组长审批;请假天数小于10天,部门经理审批;请假天数小于20天,副总经理审批;请假天数小于30天,总经理审批;请假天数超过30天,不予审批。
2、数据类定义
01 02 03 04 05 06 07 08 09 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 | /** * 请假类 */ public class LeaveRequest { //请假人 private String name; //请假理由 private String reason; //请假天数 private int day; public LeaveRequest(String name, String reason, int day) { this .name = name; this .reason = reason; this .day = day; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getReason() { return reason; } public void setReason(String reason) { this .reason = reason; } public int getDay() { return day; } public void setDay( int day) { this .day = day; } } |
3、抽象类定义
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | /** * 抽象处理者角色:请假流程抽象类 */ public abstract class Leader { //审批人 protected String name; //下一个审批者 protected Leader nextLeader; public Leader(String name) { this .name = name; } public void setNextLeader(Leader nextLeader) { this .nextLeader = nextLeader; } /** * 请假审批 * @param request */ public abstract void approve(LeaveRequest request); } |
4、具体化对象类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | /** * 具体处理者角色:小组长审批 */ public class Headman extends Leader { public Headman(String name) { super (name); } public void approve(LeaveRequest request) { //审批请假天数小于3天 if (request.getDay()<= 3 ){ System.out.println( "请假人:" +request.getName()+ ", 请假天数:" +request.getDay()+ ", 请假理由:" +request.getReason()); System.out.println( "小组长:" +name+ "审批通过" ); } else { if (nextLeader != null ){ nextLeader.approve(request); } } } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | /** * 具体处理者角色:部门经理审批 */ public class DepartmentManager extends Leader { public DepartmentManager(String name) { super (name); } public void approve(LeaveRequest request) { //审批请假天数大于3天小于10天 if (request.getDay()<= 10 ){ System.out.println( "请假人:" +request.getName()+ ", 请假天数:" +request.getDay()+ ", 请假理由:" +request.getReason()); System.out.println( "部门经理:" +name+ "审批通过" ); } else { if (nextLeader != null ){ nextLeader.approve(request); } } } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | /** * 具体处理者角色:副总经理审批 */ public class ViceGeneralManager extends Leader { public ViceGeneralManager(String name) { super (name); } public void approve(LeaveRequest request) { /** * 审批天数大于10小于20天 */ if (request.getDay()<= 20 ){ System.out.println( "请假人:" +request.getName()+ ", 请假天数:" +request.getDay()+ ", 请假理由:" +request.getReason()); System.out.println( "副总经理:" +name+ "审批通过" ); } else { if (nextLeader != null ){ nextLeader.approve(request); } } } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** * 具体处理者角色:总经理审批 */ public class GeneralManager extends Leader { public GeneralManager(String name) { super (name); } public void approve(LeaveRequest request) { //审批请假天数大于20天小于30天 if (request.getDay() <= 30 ) { System.out.println( "请假人:" + request.getName() + ", 请假天数:" + request.getDay() + ", 请假理由:" + request.getReason()); System.out.println( "总经理:" + name + "审批通过" ); } else { if (nextLeader != null ) { nextLeader.approve(request); } else { System.out.println( "请假人:" + request.getName() + ", 请假天数:" + request.getDay() + ", 请假理由:" + request.getReason()); System.out.println( "请假天数太长无法审批,请提交请假天数小于30天。" ); } } } } |
5、测试
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** * 责任链模式客户端测试类 */ public class Client { public static void main(String[] args) { Headman director = new Headman( "李大帅" ); DepartmentManager manager = new DepartmentManager( "老王" ); ViceGeneralManager viceGeneralManager = new ViceGeneralManager( "赵副" ); GeneralManager generalManager = new GeneralManager( "胡总" ); director.setNextLeader(manager); manager.setNextLeader(viceGeneralManager); viceGeneralManager.setNextLeader(generalManager); LeaveRequest leaveRequest = new LeaveRequest( "小王" , "感冒了!" , 1 ); director.approve(leaveRequest); System.out.println( "============================================" ); leaveRequest = new LeaveRequest( "小李" , "加班调休!" , 6 ); director.approve(leaveRequest); System.out.println( "============================================" ); leaveRequest = new LeaveRequest( "小胡" , "回家探亲!" , 12 ); director.approve(leaveRequest); System.out.println( "============================================" ); leaveRequest = new LeaveRequest( "小吴" , "回家探亲!" , 30 ); director.approve(leaveRequest); System.out.println( "============================================" ); leaveRequest = new LeaveRequest( "小张" , "生病休养!" , 36 ); director.approve(leaveRequest); } } |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | 请假人:小王, 请假天数:1, 请假理由:感冒了! 小组长:李大帅审批通过 ============================================ 请假人:小李, 请假天数:6, 请假理由:加班调休! 部门经理:老王审批通过 ============================================ 请假人:小胡, 请假天数:12, 请假理由:回家探亲! 副总经理:赵副审批通过 ============================================ 请假人:小吴, 请假天数:30, 请假理由:回家探亲! 总经理:胡总审批通过 ============================================ 请假人:小张, 请假天数:36, 请假理由:生病休养! 请假天数太长无法审批,请提交请假天数小于30天。 |