[特殊字符]责任链模式?代码界的“踢皮球”高手!一文搞懂!

🔗责任链模式?代码界的“踢皮球”高手!一文搞懂!

一、生活中的责任链,代码里的优雅之道

在这里插入图片描述

✨宝子们,你们有没有遇到过申请请假要层层审批的情况?组长→经理→CEO,每个人根据权限处理请求。这种 “踢皮球” 的智慧,在代码世界里就是大名鼎鼎的责任链模式!它能让请求像接力赛一样传递,直到找到合适的处理者。

二、责任链模式 360° 解析

2.1 模式定义与原理

责任链模式,简单来说,就是将请求的发送者和接收者解耦,让多个对象都有机会处理请求。它通过将这些对象连成一条链,请求在链上传递,直到有对象处理它为止。 🌐

比如在医院看病,病人挂号后,先分诊到科室,医生检查后可能安排进一步检查,最后根据结果开药。每个环节都是一个处理者,决定是否继续传递请求。

从原理上讲,责任链模式像一个接力赛,每个选手(处理者)决定是否接过接力棒(处理请求),如果不处理就传递给下一个选手。这就形成了一个动态的处理链路,非常灵活。

2.2 核心角色

在责任链模式中,有三个关键角色:抽象处理者、具体处理者和客户端。

角色作用案例中的体现
抽象处理者定义处理接口和下一个节点请假审批抽象类
具体处理者实现处理逻辑,决定是否传递组长、经理、CEO
客户端组装责任链,发起请求员工提交请假申请

抽象处理者就像是一个模板,定义了处理请求的基本方法和下一个处理者的引用。具体处理者则是实现了这些方法,根据自己的逻辑决定是否处理请求。客户端则是负责创建责任链,并发送请求。

三、Java 实战:请假审批流程

3.1 代码实现

接下来,我们用 Java 代码实现一个简单的请假审批流程。

首先,定义一个请假请求类LeaveRequest,用于封装请假的相关信息:

public class LeaveRequest {
    private String empName;  // 员工姓名
    private int leaveDays;  // 请假天数
    private String reason;  // 请假原因

    public LeaveRequest(String empName, int leaveDays, String reason) {
        this.empName = empName;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }

    public String getEmpName() {
        return empName;
    }

    public int getLeaveDays() {
        return leaveDays;
    }

    public String getReason() {
        return reason;
    }
}

然后,定义抽象处理者类AbstractApprover,它定义了处理请求的基本方法和下一个处理者的引用:

public abstract class AbstractApprover {
    protected AbstractApprover nextApprover;  // 下一个审批人

    public void setNextApprover(AbstractApprover nextApprover) {
        this.nextApprover = nextApprover;
    }

    // 处理请假请求的抽象方法
    public abstract void processRequest(LeaveRequest request);
}

接着,定义具体处理者类,分别是组长TeamLeader、经理Manager和 CEOCEOApprover,它们继承自AbstractApprover,并实现具体的处理逻辑:

// 组长审批
public class TeamLeader extends AbstractApprover {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= 1) {
            System.out.println("组长 " + request.getEmpName() + " 请假 " + request.getLeaveDays() + " 天,原因:" + request.getReason() + ",审批通过");
        } else {
            if (nextApprover != null) {
                System.out.println("组长 " + request.getEmpName() + " 请假天数超过权限,转交给经理审批");
                nextApprover.processRequest(request);
            } else {
                System.out.println("审批流程结束,无人处理该请假请求");
            }
        }
    }
}

// 经理审批
public class Manager extends AbstractApprover {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getLeaveDays() <= 3) {
            System.out.println("经理 " + request.getEmpName() + " 请假 " + request.getLeaveDays() + " 天,原因:" + request.getReason() + ",审批通过");
        } else {
            if (nextApprover != null) {
                System.out.println("经理 " + request.getEmpName() + " 请假天数超过权限,转交给CEO审批");
                nextApprover.processRequest(request);
            } else {
                System.out.println("审批流程结束,无人处理该请假请求");
            }
        }
    }
}

// CEO审批
public class CEOApprover extends AbstractApprover {
    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getLeaveDays() > 3) {
            System.out.println("CEO " + request.getEmpName() + " 请假 " + request.getLeaveDays() + " 天,原因:" + request.getReason() + ",审批通过");
        } else {
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            } else {
                System.out.println("审批流程结束,无人处理该请假请求");
            }
        }
    }
}

最后,在客户端代码中组装责任链并发起请求:

public class Client {
    public static void main(String[] args) {
        // 创建具体处理者实例
        AbstractApprover teamLeader = new TeamLeader();
        AbstractApprover manager = new Manager();
        AbstractApprover ceo = new CEOApprover();

        // 组装责任链
        teamLeader.setNextApprover(manager);
        manager.setNextApprover(ceo);

        // 创建请假请求
        LeaveRequest request1 = new LeaveRequest("张三", 1, "身体不适");
        LeaveRequest request2 = new LeaveRequest("李四", 2, "参加婚礼");
        LeaveRequest request3 = new LeaveRequest("王五", 5, "出国旅游");

        // 发起请假请求
        teamLeader.processRequest(request1);
        teamLeader.processRequest(request2);
        teamLeader.processRequest(request3);
    }
}

3.2 执行结果

运行上述代码,输出结果如下:

组长 张三 请假 1 天,原因:身体不适,审批通过
组长 李四 请假天数超过权限,转交给经理审批
经理 李四 请假 2 天,原因:参加婚礼,审批通过
组长 王五 请假天数超过权限,转交给经理审批
经理 王五 请假天数超过权限,转交给CEO审批
CEO 王五 请假 5 天,原因:出国旅游,审批通过

从结果可以看出,不同天数的请假请求在责任链上被不同的处理者处理,完美体现了责任链模式的魅力。 🌟

四、应用场景大揭秘

责任链模式在实际开发中应用广泛,以下是一些常见的场景:

4.1 审批流程

请假、报销、合同审批等流程都可以用责任链模式实现。不同级别的审批人根据权限处理请求,形成一条审批链。例如,在报销流程中,普通员工提交报销申请,先由部门经理审批,金额较大时再由财务总监审批,最后由总经理审批。

4.2 日志处理

按日志级别输出日志,如 DEBUG→INFO→ERROR。可以将不同级别的日志处理器组成责任链,根据日志级别决定由哪个处理器处理。比如,DEBUG 级别的日志先由 DEBUG 处理器处理,若不需要处理则传递给 INFO 处理器,以此类推。

4.3 拦截器 / 过滤器

在 Spring Security 中,权限校验通过多个过滤器组成的责任链实现。每个过滤器负责特定的校验逻辑,如身份验证、权限检查等。请求在过滤器链中传递,直到通过所有校验或被拦截。

4.4 游戏事件处理

在游戏中,攻击、防御、治疗等事件可以通过责任链模式处理。例如,玩家发起攻击,先由防御系统处理,若未被防御则由治疗系统处理,形成链式反应。

五、优缺点大 PK

责任链模式就像一把双刃剑,既有它的闪光点,也有一些小瑕疵。

5.1 优点

解耦:请求发送者和接收者彻底分离,发送者不用关心谁来处理请求,接收者也不用知道是谁发的请求。就像我们在网上购物,下单后,订单的处理(库存检查、支付处理等)和我们没有直接关联,各个处理环节之间也相互独立 。

灵活:责任链的结构超级灵活,可以根据需要动态调整。比如请假审批流程,公司可以根据业务变化随时调整审批人或审批顺序,而不会影响其他部分的代码 。

扩展性:新增处理者就像搭积木一样简单,符合开闭原则。例如在日志处理系统中,要新增一个日志级别处理器,只需要创建新的处理器类并加入责任链即可,原有代码完全不用动 。

5.2 缺点

性能:如果责任链很长,请求处理的时间可能会变长,影响系统性能。想象一下,一个请求要经过 100 个处理者,那得多耗时呀 。

调试:当请求出现问题时,很难定位是哪个处理者出了问题,因为要遍历整条链。就像一串糖葫芦,中间某个山楂坏了,很难一下子找到是哪一个 。

六、避坑指南

在使用责任链模式时,也有一些需要注意的地方,宝子们可要牢记哦!

6.1 合理控制链长

责任链不宜过长,一般建议不超过 5 个节点。太长的链会导致性能下降,请求处理时间变长,就像排队太长会让人失去耐心一样 。

6.2 明确终止条件

一定要设置好终止条件,防止请求在链中无限递归,陷入死循环。比如在请假审批中,CEO 审批后就应该结束流程,不能再传递下去 。

6.3 日志记录

记录请求在责任链中的流转路径,方便调试和排查问题。就像我们记录快递的物流信息一样,知道请求到了哪个处理者手中 。

6.4 线程安全

在多线程环境下,要注意线程安全问题。可以使用锁机制来控制对责任链的访问,确保请求处理的正确性 。

七、总结

责任链模式是处理流程化业务的神器,适用于有明确层级关系的审批场景、需要动态扩展处理逻辑以及希望解耦请求与处理者的情况 。

宝子们,你们在项目中用过责任链模式吗?评论区聊聊你的 “链式操作” 经验吧!👇💡

最后,给大家对比一下责任链模式和状态模式,帮助大家更好地区分它们:责任链关注请求传递,状态模式关注对象状态变化。例如:请假审批(责任链)与订单状态流转(状态模式)。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PGFA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值