概述
责任链模式是指:将一些对象连成一条链,并沿着这条链传递请求,直至某一对象处理该请求为止,这样多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系。
当一个类A的一个成员变量或一个方法涉及到了另一个类B,则A的实现依赖于B,即这两个类是互相耦合的。
该模式涉及到的角色有:
- 抽象处理者:它是一个抽象类或接口,定义了处理请求的方法。
- 具体处理者:当它收到请求后,可以选择处理请求或传给后继,因此它需要持有后继的引用。
示例
某部门申请项目费用,其大致流程为:申请人先填写申请单,交由其上级审批,而上级由分为不同级别:项目经理只能审批500元以内的申请;部门经理能审批1000元以内的申请;而总经理可以审核任意额度的申请。由于申请人事先不知道最终会有谁来处理请求,因此它只能交由其上级项目经理。
定义一个抽象处理请求
public abstract class Handler {
//持有后继的处理对象
protected Handler nextHandlerLevel = null;
public abstract String handleRequest(String applicantName, double applicantFee);
public Handler getNextHandlerLevel() {
return nextHandlerLevel;
}
public void setNextHandlerLevel(Handler nextHandlerLevel) {
this.nextHandlerLevel = nextHandlerLevel;
}
}
定义三个具体处理请求级别:
public class ProjectManager extends Handler {
@Override
public String handleRequest(String applicantName, double applicantFee) {
String curRes = "";
if(applicantFee < 500) {
if (applicantName.equals("C2y")) {
curRes = "项目经理同意项目请求";
} else {
curRes = "项目经理无法同意其他人的项目请求";
}
}else {
if(getNextHandlerLevel() != null) {
return getNextHandlerLevel().handleRequest(applicantName, applicantFee);
}
}
return curRes;
}
}
public class DeptManager extends Handler {
@Override
public String handleRequest(String applicantName, double applicantFee) {
String curRes = "";
if(applicantFee < 1000) {
if (applicantName.equals("C2y")) {
curRes = "部门经理同意项目请求";
} else {
curRes = "部门经理无法同意其他人的项目请求";
}
}else {
if(getNextHandlerLevel() != null) {
return getNextHandlerLevel().handleRequest(applicantName, applicantFee);
}
}
return curRes;
}
}
public class GeneralManager extends Handler {
@Override
public String handleRequest(String applicantName, double applicantFee) {
String curRes = "";
if(applicantFee >= 1000) {
if(applicantName.equals("C2y")) {
curRes = "总经理同意项目请求";
}else {
curRes = "总经理不同意其他人的项目请求";
}
}else {
if(getNextHandlerLevel() != null) {
return getNextHandlerLevel().handleRequest(applicantName, applicantFee);
}
}
return curRes;
}
}
测试一下:
public class Test {
public static void main(String[] args) throws Exception{
Handler pm = new ProjectManager();
Handler dm = new DeptManager();
Handler gm = new GeneralManager();
// pm->dm->gm
pm.setNextHandlerLevel(dm);
dm.setNextHandlerLevel(gm);
System.out.println(gm.handleRequest("C2y", 300));
System.out.println(gm.handleRequest("C2y", 666));
System.out.println(gm.handleRequest("C2y", 1240));
}
}
当然,我们可以通过后继处理对象来直接从项目经理跳到总经理,即每个级别都可以动态指定它的后继级别。
总结
若我们不使用责任链模式,那么在类中都会和每一个级别产生耦合关系,需要写多个if-else语句。当有了责任链,我们只需知道一个级别,然后让这个级别在内部传递即可。
纯的与不纯的责任链模式
纯的责任链模式是指 处理类要么处理完请求,要么将请求转给后继对象,不允许只处理一部分请求。
而在不纯的责任链模式中,一个请求最终可以不被任何处理类接收。
责任链模式优点
(1)降低耦合度。它将请求的发送者和接收者解耦
(2)增强了给对象指派职责的灵活性:可以通过改变链内的成员或者调动它们的次序来指派处理顺序,同时也允许动态地新增或者删除责任。
责任链模式缺点
(1)不能保证请求一定被接收。
(2)在进行代码调试时不太方便,可能会造成循环调用
责任链模式使用场景
(1)有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
(2)在不明确指定接收者的情况下,向多个对象中的一个 提交一个请求。