目录
1、责任链模式的定义
责任链模式又名职责链模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
2、责任链模式举例分析
其实我们生活中很多场合都有“责任链模式”,比如我们工作中请假时,如果请一天的假,只需要和我们的组长说就可以了;但是如果请2~5天的假时,可能就要去和我们的项目负责人请假;请5天假以上时,可能就需要去找我们的总经理请假了。
这其实就是一个责任链模式:请假时,我们发出请假的请求,一开始组长接收请求并处理,如果一天的假,他就可以处理,如果超过一天,他就得向上传递请求,传给项目负责人。项目负责人接收请求并处理,如果是2~5天的假,他就可以处理,但是如果超过5天,他又得向上传递给总经理。总经理接收请求后便开始处理.......
接下来我们基于上述例子进行代码实现。
3、责任链模式的实现
3.1 责任链模式的结构
职责链模式主要包含以下角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
本文我们弱化了客户类角色,直接传递请求,大家能理解就行。
3.2 责任链模式的代码实现
请假条类(请求类):
public class LeaveRequest { //假条类
public int leaveDays;//请假天数
public LeaveRequest(int days){
leaveDays=days;
}
}
抽象处理人类(抽象处理者角色):
public abstract class HandleRequest { //抽象处理角色
public int maxDay;//能处理的最大天数
public HandleRequest nextPerson; //更高级的领导
public HandleRequest(HandleRequest handleRequest,int maxDay){
this.nextPerson=handleRequest;
this.maxDay=maxDay;
}
public abstract void handleLeaveRequest(LeaveRequest leaveRequest);
}
组长类(具体处理者角色):
public class GroupLeader extends HandleRequest{//组长类
public GroupLeader(HandleRequest handleRequest, int maxDay) {
super(handleRequest, maxDay);
}
@Override
public void handleLeaveRequest(LeaveRequest leaveRequest) {
if(leaveRequest.leaveDays<=this.maxDay){ //在自己处理范围内则自己处理
System.out.println("组长来处理");
}
else { //不在自己处理范围内则交给领导处理
System.out.println("组长处理不了,交给组长的上级");
this.nextPerson.handleLeaveRequest(leaveRequest);
}
}
}
项目负责人类(具体处理角色):
public class ProjectLeader extends HandleRequest{//项目负责人类
public ProjectLeader(HandleRequest handleRequest, int maxDay) {
super(handleRequest, maxDay);
}
@Override
public void handleLeaveRequest(LeaveRequest leaveRequest) {
if(leaveRequest.leaveDays<=this.maxDay){ //在自己处理范围内则自己处理
System.out.println("项目负责人来处理");
}
else { //不在自己处理范围内则交给领导处理
System.out.println("项目负责人处理不了,交给项目负责人的上级");
this.nextPerson.handleLeaveRequest(leaveRequest);
}
}
}
总经理类(具体处理角色):
public class GeneralManager extends HandleRequest{//总经理类
public GeneralManager(HandleRequest handleRequest, int maxDay) {
super(handleRequest, maxDay);
}
@Override
public void handleLeaveRequest(LeaveRequest leaveRequest) {
if(leaveRequest.leaveDays<=this.maxDay){ //在自己处理范围内则自己处理
System.out.println("总经理来处理");
}
else { //不在自己处理范围内则交给领导处理
this.nextPerson.handleLeaveRequest(leaveRequest);
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
//总经理,由于总经理无论多少天都能处理,且没有上机,所以初始化如下
GeneralManager generalManager = new GeneralManager(null, Integer.MAX_VALUE);
//项目负责人,上级是总经理,处理最大天数5天
ProjectLeader projectLeader = new ProjectLeader(generalManager, 5);
//组长,上机是项目负责人,处理最大天数一天
GroupLeader groupLeader = new GroupLeader(projectLeader,1);
//离开一天
LeaveRequest leaveRequest1 = new LeaveRequest(1);
//离开三天
LeaveRequest leaveRequest2 = new LeaveRequest(3);
//离开十天
LeaveRequest leaveRequest3 = new LeaveRequest(10);
//一开始都是交给组长
System.out.println("以下是离开一天的情况");
groupLeader.handleLeaveRequest(leaveRequest1);
System.out.println("------分界线------");
System.out.println("以下是离开三天的情况");
groupLeader.handleLeaveRequest(leaveRequest2);
System.out.println("------分界线------");
System.out.println("以下是离开十天的情况");
groupLeader.handleLeaveRequest(leaveRequest3);
}
}
运行结果如下:
可见,我们通过上述实现了责任链模式,其实不止这种场景,我们很多地方实际上都用到了责任链模式,比如①Java中我们平时写的异常处理,本层能处理则处理,处理不了则向上抛。②还有比如我们CPU查数据,依次查找1、2、3级缓存,查到则本层返回,查不到才抛给下一层来处理。
4、责任链模式的优缺点
优点:
- 降低了对象之间的耦合度,该模式降低了请求发送者和接收者的耦合度。
- 增强了系统的可扩展性,可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接,一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担,每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。