责无旁贷:超酷的责任链模式

分类:Java

记得很早以前做过一个小需求,功能很简单,就是查找ip的归属地,先调用某宝的接口,如果找到了则返回结果,如果返回为空或者抛异常,再调用某度的接口,以此类推,一共有三个服务可供调用,那么,这样的代码应该怎么写呢?如何才能让代码变得可扩展性好、便于维护呢?如果你能想到使用责任链模式来实现,那么恭喜你,对于设计模式的实际应用已经有了较为深刻的理解。
我们今天就来看看,传说中的责任链模式到底是什么样的,先来看看它的定义:责无旁贷:超酷的责任链模式

让多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。把接收对象链接起来,并且让请求在这个链条上传递,直到有对象处理它为止。

责任链模式主要有三个角色:
抽象处理者(Handler):它通常是一个抽象类,定义了通用的请求处理接口,以及下一个处理者。
具体处理者(Concrete Handler):实现通用接口方法并处理请求,如果无法处理,则将请求传递给下一个处理者。
客户端(Client):创建处理链条,它不涉及请求的具体处理过程。
责无旁贷:超酷的责任链模式

责任链UML类图

我们以一个简单的例子来进一步说明责任链模式:公司员工请假需要层层审批,如果请假天数小于等于3天,小组长审批即可,如果大于3天但小于等于5天,则需要经理审批,如果大于5天,那么就需要总监进行审批。

首先定义请求类,包含请假天数和请求id:

package com.sample.patterns.cor;
// 请求类
public class Request {
    // 请假天数
    private Integer days;
    private Integer requestId;
    public Request(Integer days, Integer requestId){
        this.days = days;
        this.requestId = requestId;
    }
    public Integer getDays() {
        return days;
    }
    public void setDays(Integer days) {
        this.days = days;
    }
    public Integer getRequestId() {
        return requestId;
    }
    public void setRequestId(Integer requestId) {
        this.requestId = requestId;
    }
}

然后是抽象处理类:

package com.sample.patterns.cor;
// 抽象处理者
public abstract class Handler {
    // 下一个处理者
    private Handler successor;
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }
    public Handler getSuccessor(){
        return this.successor;
    }
    public abstract void handleRequest(Request request);
}

接下来是三个具体的处理类,分别代表小组长、经理和总监的审批,另外,此处为简化起见,没有考虑是否还有下一个处理者的情况:

package com.sample.patterns.cor;
// 小组长处理
public class LeaderHandler extends Handler{
    @Override
    public void handleRequest(Request request) {
        if(request.getDays()<=3){
            System.out.println("小组长审批通过!");
        }else{
            getSuccessor().handleRequest(request);
        }
    }
}
package com.sample.patterns.cor;
// 经理处理
public class ManagerHandler extends Handler{
    @Override
    public void handleRequest(Request request) {
        if(request.getDays()>3 && request.getDays()<=5){
            System.out.println("经理审批通过!");
        }else{
            getSuccessor().handleRequest(request);
        }
    }
}

package com.sample.patterns.cor;
// 总监处理
public class DirectorHandler extends Handler{
    @Override
    public void handleRequest(Request request) {
        if(request.getDays()>5){
            System.out.println("总监审批通过");
        }else{
            getSuccessor().handleRequest(request);
        }
    }
}


最后是客户端,它定义了处理链条上的顺序,并调用第一个处理者的方法,客户端不需要也不关心具体的处理方法,以及到底经过了几个处理者:

package com.sample.patterns.cor;

public class Client {
    public static void main(String[] args) {
        Handler leader = new LeaderHandler();
        Handler manager = new ManagerHandler();
        Handler director = new DirectorHandler();

        leader.setSuccessor(manager);
        manager.setSuccessor(director);

        Request request1 = new Request(41);
        leader.handleRequest(request1);
        Request request2 = new Request(102);
        leader.handleRequest(request2);
    }
}
同时,我们也加入了测试代码,如果请假天数是4天,那么先经由类LeaderHandler来处理,由于超过了他的职权范围,于是就交由下一个处理者,也就是ManagerHandler来审批,而如果请假天数是10天,则需要经过三个处理者,层层下推。后续如果还需要进一步加强审批管理,比如还需要总经理进行审批,那么我们直接新增一个GeneralManagerHandler即可,而不用修改现有的代码(当然,如果总监的审批权限有更改,DirectorHandler类也需要进行相应的修改)。
从上面可以看出,责任链模式把请求的发送者和接收者进行了解耦,提升了代码的灵活性和可扩展性,代码也变得非常优雅。

都看到这里了,请帮忙一键三连啊,也就是点击文末的在看、点赞、分享,这样会让我的文章让更多人看到,也会大大地激励我进行更多的输出,谢谢!

鸣谢:

https://refactoring.guru/design-patterns/chain-of-responsibility

推荐阅读:

聚沙成塔:聊聊建造者模式

公司裁员,码农竟然成了“帮凶”?(剧情杜撰)

删除重复记录但保留其中一行数据的sql写法

一条sql搞定这个需求,面试官直呼内行

MySQL如何进行表之间的关联更新

高频面试题:多线程顺序打印ABC字符20次

一网打尽:MySQL索引失效的场景大搜罗

这个设计模式的用法,一般人我不告诉他

原文始发于微信公众号(互联网全栈架构):责无旁贷:超酷的责任链模式

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/173625.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!