一个个顺序挨着来 - 责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)

  • [责任链模式(Chain of Responsibility Pattern)](#责任链模式(Chain of Responsibility Pattern))

责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许你将请求沿着处理者链条传递,直到有一个处理者能够处理它为止。这种模式避免了请求发送者和接收者之间的耦合,并且可以动态地指定一组处理者来处理请求。每个处理者都包含对下一个处理者的引用,如果当前处理者不能处理请求,它会将请求转发给下一个处理者。

太抽象了,举个现实生活中的例子

生活中,我们可能会遇到需要报销的生活场景。但是报销的时候,每个人的报销权限不一样。比如金额比较小的时候,你的领导就可以帮你审批;但是如果金额超过了你领导的审核范围,你的领导可能就把报销的交给他的上一层领导处理;他的上一层领导如果能处理就处理,处理不了,就沿着审批链条再往上进行审批。

责任链模式(Chain of Responsibility Pattern)概述

责任链结构图

责任链模式概述

  • 定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
  • 目的:解耦请求的发送者与接收者,提供一个灵活的方式来处理请求,支持动态添加或移除处理逻辑。

责任链模式涉及的角色

  1. 抽象处理者(Handler):声明了所有具体处理者必须实现的方法,通常是handle()方法。此外,它还可能包含一个指向下一个处理者的引用。
java 复制代码
public abstract class Handler {
    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(String request);
}
  1. 具体处理者(ConcreteHandler):实现了Handler接口的具体类。
java 复制代码
public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(String request) {
        if ("A".equals(request)) {
            System.out.println("Handled by ConcreteHandlerA");
        } else {
            if (successor != null) {
                successor.handleRequest(request);
            }
        }
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(String request) {
        if ("B".equals(request)) {
            System.out.println("Handled by ConcreteHandlerB");
        } else {
            if (successor != null) {
                successor.handleRequest(request);
            }
        }
    }
}
  1. 客户端(Client):客户端创建具体的处理者对象,并根据需要将它们链接起来形成一条责任链。然后,客户端将请求传递给链中的第一个处理者。
java 复制代码
public class Client {
    public static void main(String[] args) {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();

        // 构建责任链
        handlerA.setSuccessor(handlerB);

        // 发送请求
        handlerA.handleRequest("A"); // Handled by ConcreteHandlerA
        handlerA.handleRequest("B"); // Handled by ConcreteHandlerB
        handlerA.handleRequest("C"); // Not handled, no output or error
    }
}

talk is cheap, show you my code

我们还是利用本次要介绍的设计模式来实现我们给出的例子。

  1. 首先,我们定义一个ApprovalRequest类来表示审批请求:
java 复制代码
public class ApprovalRequest {
    private double amount;
    private String description;
    private boolean isApproved = false;

    public ApprovalRequest(double amount, String description) {
        this.amount = amount;
        this.description = description;
    }

    public double getAmount() {
        return amount;
    }

    public String getDescription() {
        return description;
    }

    public boolean isApproved() {
        return isApproved;
    }

    public void setApproved(boolean approved) {
        isApproved = approved;
    }
}
  1. 接下来,我们定义一个Approver接口,所有审批者都将实现这个接口:
java 复制代码
public interface Approver {
    void processRequest(ApprovalRequest request);
    Approver getNextApprover();
    void setNextApprover(Approver nextApprover);
}
  1. 我们为不同的审批级别创建具体的审批者类。例如,部门经理(DepartmentManager)、总监(Director)和CEO(ChiefExecutiveOfficer)
java 复制代码
public class DepartmentManager implements Approver {
    private Approver nextApprover;
    private static final double LIMIT = 5000.0;

    public DepartmentManager() {
    }

    @Override
    public void processRequest(ApprovalRequest request) {
        if (request.getAmount() <= LIMIT) {
            System.out.println(request.getDescription() + " is approved by Department Manager.");
            request.setApproved(true);
        } else {
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            } else {
                System.out.println(request.getDescription() + " was rejected.");
                request.setApproved(false);
            }
        }
    }

    @Override
    public Approver getNextApprover() {
        return nextApprover;
    }

    @Override
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }
}

public class Director implements Approver {
    private Approver nextApprover;
    private static final double LIMIT = 20000.0;

    // Similar methods as in DepartmentManager
    // ...
}

public class ChiefExecutiveOfficer implements Approver {
    private Approver nextApprover;

    // No limit for CEO, all requests will be approved or rejected here
    // Similar methods as in DepartmentManager and Director
    // ...
}
  1. 最后,我们可以编写一个客户端类来测试这个责任链:
java 复制代码
public class Client {
    public static void main(String[] args) {
        ApprovalRequest request1 = new ApprovalRequest(4500, "Office supplies");
        ApprovalRequest request2 = new ApprovalRequest(12000, "New computer");
        ApprovalRequest request3 = new ApprovalRequest(25000, "Conference room renovation");

        Approver departmentManager = new DepartmentManager();
        Approver director = new Director();
        Approver ceo = new ChiefExecutiveOfficer();

        departmentManager.setNextApprover(director);
        director.setNextApprover(ceo);

        departmentManager.processRequest(request1);
        System.out.println("Request1 approved? " + request1.isApproved());

        departmentManager.processRequest(request2);
        System.out.println("Request2 approved? " + request2.isApproved());

        departmentManager.processRequest(request3);
        System.out.println("Request3 approved? " + request3.isApproved());
    }
}

在这个客户端类中,我们创建了三个审批请求,并设置了审批链。然后,我们依次处理这些请求,并打印出它们是否被批准。

总结

责任链可以帮助我们降低耦合度;增加灵活性;可以帮助我们更好地组织代码。我们上面实现地责任链模式是类似与拦截器的那种方式。责任链还可以设计为一些别的方式。责任链模式一般适用于日志记录;审批流程等等。

相关推荐
源码集结号9 分钟前
基于 Spring Boot + JPA + MySQL的上门家政系统代码示例
java·前端·后端
程序员老邢43 分钟前
【技术底稿 32】Nginx 经典大坑复盘:本机公网域名自环代理,导致接口返回首页 / 404 实战排障
java·运维·nginx·前后端分离·技术底稿·后端部署
该昵称用户已存在1 小时前
从成本中心到价值引擎:MyEMS 开源系统激活企业能源数据资产
java·后端·struts
隐退山林1 小时前
JavaEE进阶:SpringBoot配置文件
java·spring boot·java-ee
阿维的博客日记2 小时前
求解深分页问题,last pk适合什么情况
java·mysql·深分页
极客先躯3 小时前
高级java每日一道面试题-2025年12月09日-实战篇[Docker]-如何配置 Docker 的日志驱动?有哪些日志驱动可选?
java·docker·日志驱动的作用与配置层级·日志驱动全览与对比·日志驱动配置的要点·日志标签定制·容器与宿主机时间戳
rabbit_pro3 小时前
Spring AI使用Ollama
java·人工智能·spring
Mike117.3 小时前
GBase 8a 物化视图依赖和 DDL 风险排查记录
java·服务器·前端
李少兄3 小时前
领域驱动设计与 Clean Code 的实践
java·数据库·领域驱动