1 定义
责任链模式(Chain of Responsibility Pattern)又叫职责链模式或者职责连锁模式,属于行为型设计模式,它主要是为请求者进行发送请求动作时创建一个接收的对象链,而链上每一个接收者都包含着下一个接收者的引用,如果当前接收者不能处理指定的请求,便将该请求传递给下一个接收者,依此类推直到有一个接收者能为其处理为止,而请求者也并不知道发起的请求会在链上哪个接收者最终处理。例如现实场景,我们工作中需要请假,假如请假天数是3天内是部门经理审批;如果5天内是先部门经理审批,接着是总监审批;如果10天内除了经理和总监审批外还要老板审批。在这个请假的请求中,领导们成了一个接收链,但最终由哪个领导来审批请假取决于发起请假是多少天。
2 实现
责任链模式一般包含了3个角色,分别是:
- 请求(Request),用于定义请求的信息,例如上述定义举例中请假的天数和其它请假信息。
- 抽象接收(Handler),用于定义一个处理请求的接口以及持有一个上级接收者,例如上述定义举例的领导。
- 具体接收(ConcreteHandler),继承抽象接收父类,具体接收角色可以有多个,它们组成了接收链,例如上述定义举例的经理、总监和老板。
请求类,定义了请假天数信息:
public class LeaveRequest {
private int mDayCount;
public LeaveRequest(int dayCount) {
mDayCount = dayCount;
System.out.println("请假" + mDayCount + "天");
}
public int getDayCount() {
return mDayCount;
}
}
抽象接收类,定义了一个上级接收者的对象以及定义一个处理请求的抽象方法:
public abstract class Job {
protected String mName;
protected Job mSuperiorJob;
public Job(String name) {
mName = name;
}
public void setSuperiorJob(Job superiorJob) {
mSuperiorJob = superiorJob;
}
public abstract void handle(LeaveRequest leaveRequest);
}
具体接收类,实现父类的处理请求抽象方法,分别是经理、总监和老板三个具体接收类:
public class ManagerJob extends Job {
public ManagerJob() {
super("经理");
}
@Override
public void handle(LeaveRequest leaveRequest) {
if (leaveRequest.getDayCount() < 3) {
System.out.println(mName + "批准");
} else if (mSuperiorJob != null) {
mSuperiorJob.handle(leaveRequest);
} else {
System.out.println(mName + "不批准");
}
}
}
public class MajordomoJob extends Job {
public MajordomoJob() {
super("总监");
}
@Override
public void handle(LeaveRequest leaveRequest) {
if (leaveRequest.getDayCount() < 5) {
System.out.println(mName + "批准");
} else if (mSuperiorJob != null) {
mSuperiorJob.handle(leaveRequest);
} else {
System.out.println(mName + "不批准");
}
}
}
public class BossJob extends Job {
public BossJob() {
super("老板");
}
@Override
public void handle(LeaveRequest leaveRequest) {
if (leaveRequest.getDayCount() < 10) {
System.out.println(mName + "批准");
} else {
System.out.println(mName + "不批准");
}
}
}
客户端:
public class Main {
public static void main(String[] args) {
// 创建领们的对象
ManagerJob managerJob = new ManagerJob();
MajordomoJob majordomoJob = new MajordomoJob();
BossJob bossJob = new BossJob();
// 设置领导们的上下级关系
managerJob.setSuperiorJob(majordomoJob);
majordomoJob.setSuperiorJob(bossJob);
LeaveRequest leaveRequest1 = new LeaveRequest(1);
managerJob.handle(leaveRequest1);
LeaveRequest leaveRequest2 = new LeaveRequest(3);
managerJob.handle(leaveRequest2);
LeaveRequest leaveRequest3 = new LeaveRequest(6);
managerJob.handle(leaveRequest3);
LeaveRequest leaveRequest4 = new LeaveRequest(10);
managerJob.handle(leaveRequest4);
}
}
输出结果:
请假1天
经理批准
请假3天
总监批准
请假6天
老板批准
请假10天
老板不批准
3 区别
责任链模式和状态模式都是行为型设计模式,而且它们在使用上非常相似,我们来看看它们的区别:
- 状态模式为了解决状态的条件表过式过于复杂时的工作流,将每个节点进行逻辑封装和节点内决定下一节点的跳转,体现出工作流节点状态的变化。
- 责任链模式用多个接收对象连成一个链为了处理发起的请求任务归属责任权限的问题,接收链由外部指定上下级关系,体现出接收对象权限的控制。
- 如果两种模式要使用请假这个例子表达的话,状态模式更像是OA系统固定的请假流程,一个领导审批完后状态发生化变,然后自动转交到下一个领导去审批,而责任链模式更像是拿着请假条当面找领导签名,中间如果总监不在,甚至可以跳过他直接找老板签,发起者可以决定接收者。
4 总结
责任链模式使请求者和接收者得到很好的解耦,请求者不需要知道哪一个接收对象最终处理了这个请求,这样可以在不影响请求者的情况下动态重新组织和分配责任。又因为接收链允许请求者动态新增或删除责任链,使增强了对象指派职责的灵活性。而且链中的各个接收对象本身也不需知道链的结构,它们仅需要保持一个指向其后继者的引用即可,这样也使职责链简化对象的相互连接。但是如果整条接收链过长而且请求从头部一直遍历到尾部这样也会产生一定的性能问题且也增加了调试时间。