设计模式之责任链模式

责任链模式

本文主讲设计模式之责任链模式,其精髓在于构建一条链条

作者:zsl

一个例子

假设这样一个场景(不一定完全正确),有个员工需要向领导请示一定资金的使用,由于不同的金额级别(级别不同,金额不同),请示领导的级别假定也不一致。我们假设有三个领导岗位A、B、C,分别分别处理不同级别的金额,先用类图模拟该场景:

在这里插入图片描述

该类图很容易读懂,一个员工接口,包含两个方法;一个领导接口,包含一个处理请求的方法,我们用代码实现该类图:

1、员工接口及其实现类

/**
 * 接口
 * @author ZSL
 */
public interface IEmployee {

    /**
     * 获取请求的级别
     * @return 级别
     */
    Integer getType();

    /**
     * 获取请求内容
     * @return 请求内容
     */
    String getRequest();
}
/**
 * @author zsl
 * @date 2020/8/23
 */
public class Employee implements IEmployee{

    /**
     * 类型
     */
    private Integer type;

    /**
     * 内容
     */
    private String request;

    public Employee(Integer type, String request) {
        this.type = type;
        this.request = request;
    }

    @Override
    public Integer getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }

}

2、领导接口及其实现类

/**
 * @author zsl
 * @date 2020/8/23
 */
public interface ILeaderHandler {

    /**
     * 处理请求
     */
    void handlerRequest(IEmployee employee);
}
/**
 * @author zsl
 * @date 2020/8/23
 * 假定只处理级别1
 */
public class LeaderA implements ILeaderHandler{
    @Override
    public void handlerRequest(IEmployee employee) {
        System.out.println("员工的请求是:"+employee.getRequest());
        System.out.println("LeaderA的答复:同意!");
    }
}
/**
 * @author zsl
 * @date 2020/8/23
 * 假定只处理级别2
 */
public class LeaderB implements ILeaderHandler{
    @Override
    public void handlerRequest(IEmployee employee) {
        System.out.println("员工的请求是:"+employee.getRequest());
        System.out.println("LeaderB的答复:同意!");
    }
}
/**
 * @author zsl
 * @date 2020/8/23
 * 假定只处理级别3
 */
public class LeaderC implements ILeaderHandler{
    @Override
    public void handlerRequest(IEmployee employee) {
        System.out.println("员工的请求是:"+employee.getRequest());
        System.out.println("LeaderC的答复:同意!");
    }
}

代码编写完毕,我们进行测试:

/**
 * @author zsl
 * @date 2020/8/23
 */
public class Client {

    public static void main(String[] args) {

        //准备数据
        ArrayList<IEmployee> list = new ArrayList<>(3);
        list.add(new Employee(1,"请求使用级别1的金额"));
        list.add(new Employee(2,"请求使用级别2的金额"));
        list.add(new Employee(3,"请求使用级别3的金额"));
        
        //定义三个请示对象
        ILeaderHandler leaderA = new LeaderA();
        ILeaderHandler leaderB = new LeaderB();
        ILeaderHandler leaderC = new LeaderC();
        for (IEmployee emp:list) {
            if (emp.getType()==1){
                leaderA.handlerRequest(emp);
            }else if (emp.getType()==2){
                leaderB.handlerRequest(emp);
            }else if (emp.getType()==3){
                leaderC.handlerRequest(emp);
            }else {
                System.out.println("--------无法请示--------");
            }
        }
    }
}

/**
结果:
员工的请求是:请求使用级别1的金额
LeaderA的答复:同意!
员工的请求是:请求使用级别2的金额
LeaderB的答复:同意!
员工的请求是:请求使用级别3的金额
LeaderC的答复:同意!
*/

测试结果显示,完全正确!不同级别的领导审批不同级别的金额,实现了这一需求。

结果正确,但是代码看起来很奇怪了,有几个问题:

1、首先看到client场景类,代码过于臃肿,if…else的判断条件,随着后期越来越多的领导审批,可以预想后期会有很多很多if…else,阅读成本高;

2、按照正常情况下,一般向某位领导请示,那么这位领导有义务、责任处理该请求,而这里确实client类进行组装,职责界限不清晰

3、前面提到,后续可能会增加不同的领导审批,会有多个实现类,这样就得重新修改client类,耦合过高,违背开闭原则。

4、有可能出现本该去领导B请示,却去了领导A,这种情况没有处理方法。

针对以上这种问题,我们需要重新考虑。员工向领导请示,那么员工必须得到一个响应,不管是哪个领导批的,可能领导A,领导B,领导C…那么,我们可以串成一个"链条",A–>B–>C,每个领导要么承担责任作出回应,要么转发给后面的领导处理,如下图:

在这里插入图片描述

优化例子

从上面的分析我们知道,需要构建一个链条(链条是需要能够链接下一个处理对象),要符合相关的设计原则,我们重新设计类图:

在这里插入图片描述

我们调整了类图,领导实现类只需要实现父类中的抽象方法response就可以。我们看下具体实现。

抽象类LeaderHandler及其实现类:

/**
 * @author zsl
 * @date 2020/8/23
 */
public abstract class LeaderHandler {
    /**级别1*/
    public static final Integer LEVEL_1 = 1;

    /**级别2*/
    public static final Integer LEVEL_2 = 2;

    /**级别3*/
    public static final Integer LEVEL_3 = 3;
    /**能处理的级别*/
    private Integer level = 0;
    /**责任传递,下一个责任人*/
    private LeaderHandler nextHandler;

    public LeaderHandler(Integer level) {
        this.level = level;
    }

    public void setNextHandler(LeaderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 子类实现回应,具体由子类决定
     * @param employee
     */
    protected abstract void response(IEmployee employee);

    /**
     * 处理请求
     * @param employee
     */
    public final void handlerRequest(IEmployee employee){
        if (employee.getType().equals(this.level)){
            this.response(employee);
        }else {
            if (this.nextHandler != null){
                this.nextHandler.handlerRequest(employee);
            }else {
                System.out.println("----暂时无法请示,默认结果拒绝---");
            }
        }
    }
}
/**
 * @author zsl
 * @date 2020/8/23
 */
public class LeaderA extends LeaderHandler {
    public LeaderA() {
        super(LeaderHandler.LEVEL_1);
    }

    @Override
    protected void response(IEmployee employee) {
        System.out.println("***向leadeA请示***");
        System.out.println(employee.getRequest());
        System.out.println("leaderA答复:同意!");
    }
}
/**
 * @author zsl
 * @date 2020/8/23
 */
public class LeaderB extends LeaderHandler {
    public LeaderB() {
        super(LeaderHandler.LEVEL_2);
    }

    @Override
    protected void response(IEmployee employee) {
        System.out.println("***向leadeB请示***");
        System.out.println(employee.getRequest());
        System.out.println("leaderB答复:同意!");
    }
}
/**
 * @author zsl
 * @date 2020/8/23
 */
public class LeaderC extends LeaderHandler {
    public LeaderC() {
        super(LeaderHandler.LEVEL_3);
    }

    @Override
    protected void response(IEmployee employee) {
        System.out.println("***向leadeC请示***");
        System.out.println(employee.getRequest());
        System.out.println("leaderC答复:同意!");
    }
}

场景测试类及其结果:

/**
 * @author zsl
 * @date 2020/8/23
 */
public class LeaderC extends LeaderHandler {
    public LeaderC() {
        super(LeaderHandler.LEVEL_3);
    }

    @Override
    protected void response(IEmployee employee) {
        System.out.println("***向leadeC请示***");
        System.out.println(employee.getRequest());
        System.out.println("leaderC答复:同意!");
    }
}
/**
***向leadeA请示***
请求使用级别1的金额
leaderA答复:同意!
***向leadeB请示***
请求使用级别2的金额
leaderB答复:同意!
***向leadeC请示***
请求使用级别3的金额
leaderC答复:同意!
*/

结果正确,场景类不用判断到底是哪个领导处理的,抽象类的子类可以往下增加下去,只需要扩展链条。这就是责任链模式

定义

责任链模式的定义如下:

使得多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

从定义上看,责任链的重点就是链条,由一条链去处理相似的请求,并在链中决定谁来处理这个请求并返回相应的结果。优点非常显著,请求和处理分开,请求者不知道具体是谁处理的,处理者也不用知道请求的全貌,两者解耦,提高系统的灵活性。当然也有其缺点:从上面看到,链条必须从头遍历到尾,如果链条过长,性能会是一个大问题,这个需要在开发中注意。

另外,我们看到上面的例子中的final方法,这其实是一个模板方法模式的使用,感兴趣的读者可以了解一下这个设计模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值