howema 2020-05-16
系统中如果存在多个对象可以处理一个同一请求,可以通过职责链模式将这些处理请求的对象连成一条链,让请求沿着该链进行传递。如果链上的对象可以处理该请求则进行处理,否则将请求转发给下家处理
很多情况下,可以处理某个请求的对象不止一个,如大学里的奖学金审批,学生先向辅导员提交审批表,辅导员签字审批后再交给系主任签字审批,接着是院长审批,最后可能是校长审批,在这个过程中,奖学金申请表可以看作一个请求对象,不同级别审批者都可以处理该请求,除了辅导员之外,学生不需一一和其他审批者交互,只需等待结果即可。审批过程中如果某一审批者认为不符合条件,则请求中止,否则将请求传递给下一审批者,最后由校长拍板。
在这个过程中,辅导员、系主任、院长、校长构成一条链,申请表沿着这条链传递,就叫职责链。职责链可以是一条直线、一个环或一个树形结构,常见的职责链是直线型。请求沿着链传递,由链上的处理者对请求进行处理,客户无须关心请求的处理和传递细节,实现请求发送者和请求处理者解耦。
避免请求者与接收者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理为止。职责链模式也叫责任链模式,它是一种对象行为型模式。
Handler(抽象处理者)
定义了一个处理请求的接口,由于不同的具体处理者处理请求方式不同,因此在其中定义抽象请求处理方法。在抽象处理者中定义一个自类型(抽象处理者类型)的对象,作为对下家的引用。
ConcreteHandler(具体处理者)
具体处理者是抽象处理者子类,实现抽象请求处理方法,处理用户请求。在处理请求之前要进行判断,看是否具有相应处理权限,如果可以处理就处理,否则将请求转发给后继者。
Client(客户类)
用于向链中对象提出最初的请求,客户类只关心链的源头,而无须关心请求的处理细节和传递过程。
某系统提供一个假条审批的模块,如果员工请假天数小于 3 天,主任可以审批该假条;如果员工请假天数大于等于 3 天,小于 10 天,经理可以审批;如果员工请假天数大于等于 10 天,小于 30 天,总经理可以审批;如果超过 30 天,总经理也不能审批,提示相应的拒绝信息。
请求类 LeaveRequest(请假条类)
// 封装请求的相关信息,以便处理者对其进行处理 public class LeaveRequest { private String leaveName; private int leaveDays; public LeaveRequest(String leaveName, int leaveDays) { this.leaveName = leaveName; this.leaveDays = leaveDays; } public void setLeaveName(String leaveName) { this.leaveName = leaveName; } public void setLeaveDays(int leaveDays) { this.leaveDays = leaveDays; } public String getLeaveName() { return leaveName; } public int getLeaveDays() { return leaveDays; } }
抽象处理类 Leader(领导类)
public abstract class Leader { protected String name; protected Leader successor; // 作为对下家的引用 public Leader(String name) { this.name = name; } public void setSuccessor(Leader successor) { this.successor = successor; } public abstract void handleRequest(LeaveRequest request); }
具体处理者 Director(主任类)
public class Director extends Leader { public Director(String name) { super(name); } @Override public void handleRequest(LeaveRequest request) { if (request.getLeaveDays() < 3) { System.out.println("主任" + name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays() + "天"); } else { if (this.successor != null) { this.successor.handleRequest(request); } } } }
具体处理者 Manager(经理类)
public class Manager extends Leader { public Manager(String name) { super(name); } @Override public void handleRequest(LeaveRequest request) { if (request.getLeaveDays() < 10) { System.out.println("经理" + name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays() + "天"); } else { if (this.successor != null) { this.successor.handleRequest(request); } } } }
具体处理者 GeneralManager(总经理类)
public class GeneralManager extends Leader { public GeneralManager(String name) { super(name); } @Override public void handleRequest(LeaveRequest request) { if (request.getLeaveDays() < 30) { System.out.println("总经理" + name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays() + "天"); } else { System.out.println("想请假" + request.getLeaveDays() + "天?你是不想干了吧!"); } } }
客户端测试类 Client
public class Client { public static void main(String[] args) { Leader director = new Director("王明"); Leader manager = new Manager("赵强"); Leader generalManager = new GeneralManager("陈勇"); director.setSuccessor(manager); manager.setSuccessor(generalManager); LeaveRequest lr1 = new LeaveRequest("张三", 2); director.handleRequest(lr1); LeaveRequest lr2 = new LeaveRequest("李四", 5); director.handleRequest(lr2); LeaveRequest lr3 = new LeaveRequest("王五", 15); director.handleRequest(lr3); LeaveRequest lr4 = new LeaveRequest("赵六", 45); director.handleRequest(lr4); } }
运行结果
职责链模式优点如下:
职责链模式缺点如下:
以下情况可以考虑使用职责链模式:
一个纯的职责链模式要求某一处理者对象要么接收请求,承担责任,要么把责任推给下家。在一个不纯的职责链模式里面,一个请求可以被由某一处理对象承担一部分责任后,又将责任往下传,或者最终不被任何接收端对象所接收。实际中我们接触到的大多是不纯的职责链模式。