定义:将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。
场景:打牌时,轮流出牌;接力赛跑;大学中,奖学金审批;公司中,公文审批
——公司里,报销单据需要经过流程:
申请人填单申请,申请给经理
小于1000,经理审查
超过1000,交给总经理审批
总经理审批通过
——公司里面,请假条审批过程:
如果请假天数小于3天,主任审批
如果请假天数大于等于3天,小于10天,经理审批
如果大于等于10天,小于30天,总经理审批
如果大于等于30天,提示拒绝
以上面请假条审批过程为例:
1. 创建一个LeaveRequst类:
1 package com.ztq.chainOfResp; 2 3 /*** 4 * 封装请假的基本信息 5 * @author ZTQ 6 * 7 */ 8 public class LeaveRequest { 9 private String empName;10 private int leaveDays;11 private String reason;12 13 public LeaveRequest(String empName, int leaveDays, String reason) {14 super();15 this.empName = empName;16 this.leaveDays = leaveDays;17 this.reason = reason;18 }19 public String getEmpName() {20 return empName;21 }22 public void setEmpName(String empName) {23 this.empName = empName;24 }25 public int getLeaveDays() {26 return leaveDays;27 }28 public void setLeaveDays(int leaveDays) {29 this.leaveDays = leaveDays;30 }31 public String getReason() {32 return reason;33 }34 public void setReason(String reason) {35 this.reason = reason;36 }37 38 }
2.创建Leader抽象类:
1 package com.ztq.chainOfResp; 2 3 /*** 4 * 抽象类 5 * @author ZTQ 6 * 7 */ 8 public abstract class Leader { 9 protected String name;10 protected Leader nextLeader; //责任链上的后继对象11 public Leader(String name) {12 super();13 this.name = name;14 }15 16 //设定责任链的后继对象17 public void setNextLeader(Leader nextLeader) {18 this.nextLeader = nextLeader;19 }20 21 //处理请求的核心的业务方法22 public abstract void handleRequest(LeaveRequest request);23 }
3. 创建Director类:
1 package com.ztq.chainOfResp; 2 3 /*** 4 * 主任 5 * @author ZTQ 6 * 7 */ 8 public class Director extends Leader{ 9 10 public Director(String name) {11 super(name);12 13 }14 15 @Override16 public void handleRequest(LeaveRequest request) {17 if(request.getLeaveDays() < 3){18 System.out.println("员工:" + request.getEmpName() + "请假,天数:" + request.getLeaveDays() + ", 理由:" + request.getReason());19 System.out.println("主任:" + this.name + "审批通过!");20 }else{21 if(this.nextLeader != null){22 this.nextLeader.handleRequest(request);23 }24 }25 }26 27 }
4. 创建Manager类:
1 package com.ztq.chainOfResp; 2 3 /*** 4 * 经理 5 * @author ZTQ 6 * 7 */ 8 public class Manager extends Leader{ 9 10 public Manager(String name) {11 super(name);12 13 }14 15 @Override16 public void handleRequest(LeaveRequest request) {17 if(request.getLeaveDays() < 10){18 System.out.println("员工:" + request.getEmpName() + "请假,天数:" + request.getLeaveDays() + ", 理由:" + request.getReason());19 System.out.println("经理:" + this.name + "审批通过!");20 }else{21 if(this.nextLeader != null){22 this.nextLeader.handleRequest(request);23 }24 }25 }26 27 }
5.创建GeneralManager类:
1 package com.ztq.chainOfResp; 2 3 /*** 4 * 总经理 5 * @author ZTQ 6 * 7 */ 8 public class GeneralManager extends Leader{ 9 10 public GeneralManager(String name) {11 super(name);12 13 }14 15 @Override16 public void handleRequest(LeaveRequest request) {17 if(request.getLeaveDays() < 30){18 System.out.println("员工:" + request.getEmpName() + "请假,天数:" + request.getLeaveDays() + ", 理由:" + request.getReason());19 System.out.println("总经理:" + this.name + "审批通过!");20 }else{21 System.out.println("莫非" + request.getEmpName() + "想辞职,居然请假" + request.getLeaveDays() + "天!");22 }23 }24 25 }
6.创建测试类Client:
1 package com.ztq.chainOfResp; 2 3 public class Client { 4 public static void main(String[] args) { 5 Leader a = new Director("张三"); 6 Leader b = new Manager("李四"); 7 Leader c = new GeneralManager("王五"); 8 9 //组织责任链对象的关系10 a.setNextLeader(b);11 a.setNextLeader(c);12 13 //开始请假操作14 LeaveRequest req1 = new LeaveRequest("Tom", 10, "回英国老家探亲!");15 a.handleRequest(req1);16 }17 }
7.运行结果:
员工:Tom请假,天数:10, 理由:回英国老家探亲!总经理:王五审批通过!
8.UML图:
开发中常见的场景:
——Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch。
——JavaScript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理采用观察者模式。
——Servlet开发中,过滤器的链式处理
——Struts2中,拦截器的调用也是典型的责任链模式