设计模式——责任链模式

170 阅读3分钟

概述

责任链模式是指:将一些对象连成一条链,并沿着这条链传递请求,直至某一对象处理该请求为止,这样多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合关系。

当一个类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)在不明确指定接收者的情况下,向多个对象中的一个 提交一个请求。

参考资料

Java设计模式之责任链模式、职责链模式