Java设计模式——职责链模式:解锁高效灵活的请求处理之道

嘿,各位 Java 编程大神和爱好者们!今天咱们要一同深入探索一种超厉害的设计模式——职责链模式。它就像一条神奇的“处理链”,能让请求在多个对象之间有条不紊地传递,直到找到最合适的“处理者”。准备好跟我一起揭开它神秘的面纱,看看如何用代码实现这种强大的模式,让我们的程序变得更加智能和灵活吧!💥

一、职责链模式:请求处理的“智能传送带”🎯

(一)模式定义与神奇特点

职责链模式可是对象行为模式家族里的“明星成员”哦!想象一下,有一群对象像链条上的环一样紧密相连,每个对象都知道下一个对象是谁(持有下家的引用)。当一个请求像小包裹一样在这条链上传递时,它会逐个经过这些对象。而发出请求的客户端呢,就像把包裹送到快递公司后就安心等待结果一样,完全不用操心到底是哪个对象最终会处理这个请求。这种模式最大的魅力在于它赋予了系统超级强大的灵活性。比如说,我们可以随时调整这条链的结构,添加、删除或者重新排列处理者,而客户端那边却感觉不到任何变化,就像魔法一样!🧙‍♂️

用一个超形象的比喻来理解,职责链模式就像是一场接力赛跑,每个选手(处理者)都有自己的能力范围(处理条件)。当接力棒(请求)传来时,如果这个选手有能力完成接下来的路程(处理请求),那就全力冲刺;如果觉得自己力不从心,就迅速把接力棒交给下一个选手,直到找到那个能冲过终点线(处理请求)的“大神”选手。

再举个生活中的例子,就拿击鼓传花来说吧。一群小伙伴围成一个圈(形成责任链),鼓声响起时开始传花(请求传递)。每个小伙伴就像是链上的一个处理者,当花传到自己手上时,如果鼓声停止(满足某种条件),那这个小伙伴就要表演节目(处理请求);如果鼓声还在响,就赶紧把花传给下一个小伙伴。这里的小伙伴们可以站成直线、围成环形或者组成树状结构的一部分,具体怎么站完全取决于大家想怎么玩这个游戏(业务逻辑和需求)。🎊

(二)模式结构大揭秘

  1. 抽象处理者(Handler):链的“基石”与“规则制定者”
    • 抽象处理者就像是整个职责链的“总设计师”,它定义了处理请求的统一接口,就像给所有处理者制定了一套必须遵守的“游戏规则”。在某些情况下,它还会规定怎么设置和获取下一个处理者(下家)的方法。一般来说,它会以抽象类或者接口的形式存在,为具体的处理者提供了一个清晰的行为框架和接口规范,确保所有处理者都能“按章办事”。就好比建筑蓝图,规定了房子该怎么盖,每个房间的布局和功能一样。🏠
  2. 具体处理者(ConcreteHandler):请求的“接收者”与“传递者”
    • 具体处理者可是链上的“实干家”,当请求送到它面前时,它有两种选择。一种是根据自己的能力和判断,决定是否亲自处理这个请求。如果它觉得自己能行,就会按照自己的方式处理请求,就像厨师根据订单(请求)烹饪美食(处理逻辑);另一种情况是,如果它觉得自己搞不定,或者根据业务规则应该让更厉害的人来处理,它就会毫不犹豫地把请求转交给下家。因为它知道下家是谁(持有下家引用),所以能轻松地把请求传递下去,让请求继续在链上“旅行”。就像快递员,如果发现包裹的目的地不在自己的配送范围内,就会转交给下一个区域的快递员。🚚

(三)代码实现:构建职责链

下面是一个用 Java 实现的职责链模式的简单示例代码,让我们一起来看看它是如何工作的。

// 抽象处理者(Handler)
abstract class Handler {
    // 持有下一个处理者的引用
    protected Handler successor;

    // 设置下一个处理者的方法
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    // 抽象的处理请求方法,具体处理逻辑由子类实现
    abstract public void handleRequest(int request);
}

// 具体处理者 1(ConcreteHandler1)
class ConcreteHandler1 extends Handler {
    @Override
    public void handleRequest(int request) {
        // 如果请求在 0 到 10 之间(这里只是一个简单的示例条件),则由当前处理者处理
        if (request >= 0 && request < 10) {
            System.out.println(this + " handled request " + request);
        } else if (successor!= null) {
            // 否则,将请求传递给下一个处理者(如果有下家的话)
            successor.handleRequest(request);
        }
    }
}

// 具体处理者 2(ConcreteHandler2)
class ConcreteHandler2 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 10 && request < 20) {
            System.out.println(this + " handled request " + request);
        } else if (successor!= null) {
            successor.handleRequest(request);
        }
    }
}

// 具体处理者 3(ConcreteHandler3)
class ConcreteHandler3 extends Handler {
    @Override
    public void handleRequest(int request) {
        if (request >= 20 && request < 30) {
            System.out.println(this + " handled request " + request);
        } else if (successor!= null) {
            successor.handleRequest(request);
        }
    }
}

// 客户端测试类
public class Client {
    public static void main(String[] args) {
        // 创建处理者对象
        Handler h1 = new ConcreteHandler1();
        Handler h2 = new ConcreteHandler2();
        Handler h3 = new ConcreteHandler3();

        // 设置处理者之间的链关系,形成 h1 -> h2 -> h3 的链
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);

        // 生成一些请求并处理
        int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};

        for (int request : requests) {
            h1.handleRequest(request);
        }
    }
}

Responsibility.jpg

(四)纯与不纯的职责链模式

  1. 纯职责链模式:规则严格的“处理链”
    • 在纯职责链模式的世界里,规则那是相当严格的。对于每一个具体的处理者来说,当收到请求时,它只能二选一:要么勇敢地承担起处理请求的全部责任,就像独自扛起一座大山;要么毫不犹豫地把责任推给下家,绝不拖泥带水。而且,在这条链上,每个请求就像一个被精心安排的小旅客,必定会被某个处理者收留并妥善处理,绝对不会出现被忽视、流落街头的情况。不过呢,这种模式在现实生活中的例子比较少,因为它的实现和应用场景相对来说有点“挑食”,要求比较高,不够灵活。就像一个只接受特定规格零件的精密仪器,稍微有点不匹配就无法工作。🔍
  2. 不纯职责链模式:适应变化的“万能链”
    • 不纯职责链模式就随和多了,它允许请求在传递过程中,即使经过了所有的处理者,也可能找不到一个愿意收留它的“家”。这种模式在实际开发中可是非常受欢迎的“大众明星”,因为它能更好地应对复杂多变的业务需求。比如说,在某些业务场景中,一个请求可能像一个挑剔的顾客,在经过一系列的服务者(处理者)后,还是没有找到满意的服务(没有合适的处理者)。这时候,系统可以根据预先设定的策略,比如记录下这个“挑剔顾客”的需求(记录日志),或者礼貌地告诉它“不好意思,我们无法满足您的需求”(返回错误信息)。就像一家餐厅,如果遇到顾客点了菜单上没有的菜品,服务员可以记录下来反馈给厨房(记录日志),或者向顾客解释并推荐其他菜品(返回错误信息)。🍽

(五)实际应用案例:采购审批系统中的职责链

让我们来看一个更贴近实际工作场景的例子——采购审批系统。

// 抽象审批者(Approver)
abstract class Approver {
    // 审批者姓名
    protected String name;
    // 持有下一个审批者的引用
    protected Approver successor;

    // 构造函数,初始化审批者姓名
    public Approver(String name) {
        this.name = name;
    }

    // 设置下一个审批者的方法
    public void setSuccessor(Approver successor) {
        this.successor = successor;
    }

    // 抽象的审批请求方法,具体审批逻辑由子类实现
    abstract public void processRequest(PurchaseRequest request);
}

// 主管审批者(Director)
class Director extends Approver {
    public Director(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 10000.0) {
            System.out.println(this + " " + name + " approved request# " + request.getNumber());
        } else if (successor!= null) {
            successor.processRequest(request);
        }
    }
}

// 副总裁审批者(VicePresident)
class VicePresident extends Approver {
    public VicePresident(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 25000.0) {
            System.out.println(this + " " + name + " approved request# " + request.getNumber());
        } else if (successor!= null) {
            successor.processRequest(request);
        }
    }
}

// 总裁审批者(President)
class President extends Approver {
    public President(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() < 100000.0) {
            System.out.println(this + " " + name + " approved request# " + request.getNumber());
        } else {
            System.out.println("Request# " + request.getNumber() + " requires an executive meeting!");
        }
    }
}

// 采购请求类(PurchaseRequest)
class PurchaseRequest {
    private double amount;
    private int number;

    public PurchaseRequest(double amount, int number) {
        this.amount = amount;
        this.number = number;
    }

    public double getAmount() {
        return amount;
    }

    public int getNumber() {
        return number;
    }
}

在这个采购审批系统中,我们定义了不同级别的审批者,从主管、副总裁到总裁,他们就像一条职责链上的各个环节。当一个采购请求(就像一个任务包裹)被提交后,它会从主管开始,沿着这条审批链依次传递。如果采购金额比较小,比如小于 10000 元,主管就可以直接批准(处理请求);如果金额超过了主管的审批权限,主管就会把请求交给副总裁。副总裁也会根据金额大小决定是否批准,如果金额超过了副总裁的权限,就继续传递给总裁。这样,不同金额的采购请求就能找到合适的审批者进行处理。而且,如果未来公司的审批流程发生了变化,比如增加了新的审批层级或者修改了审批金额的限制,我们只需要在相应的审批者类中进行修改,就像调整链条上的某个环节一样,不会对整个审批系统的结构造成太大的影响。这就是职责链模式在实际应用中的强大之处,它让系统变得更加灵活和易于维护。💼

二、总结与展望:职责链模式的无限潜力💡

通过对职责链模式的深入学习,我们就像获得了一把神奇的钥匙,可以打开高效灵活处理请求的大门。它不仅让我们的代码结构更加清晰,各个处理者之间的职责分明,还让系统能够轻松应对各种变化,无论是业务规则的调整还是处理流程的优化。

在未来的开发中,我们可以继续探索职责链模式的更多应用场景,比如在工作流系统、消息处理系统、异常处理机制等方面都可以发挥它的优势。同时,我们也可以结合其他设计模式,如工厂模式来创建处理者对象,或者结合装饰者模式来增强处理者的功能,让我们的程序更加健壮和强大。相信只要我们善于运用这些设计模式,就能打造出更加优秀、高效的软件系统,在编程的世界里创造更多的精彩!🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/925865.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【四轴】利用PWM捕获解析接收机信号

在学习这部分之间&#xff0c;建议大家先看之前这篇博客&#xff0c;里面包含对PWM一些重要概念的基本介绍。 【四轴】利用PWM输出驱动无刷电机-CSDN博客 1. 基本原理 1.1 PWM是什么 这一部分可以看我之前的博客&#xff0c;已经对PWM有了基本的介绍。 1.2 什么叫捕获PWM波&…

HTTP 1

文章目录 1.2个简单的预备知识域名统一资源定位符 URL完整的URL 2. http请求和响应 格式画出来&#xff0c;两个工具见一见http请求/响应的样子3. 写一个最简单的httpserver&#xff0c;用浏览器直接测试recvsend处理请求stringstream 字符串分割工具wget 4. 读http报文的细节 …

【mac】mac自动定时开关机和其他常用命令,管理电源设置的工具pmset

一、操作步骤 1、打开终端 2、pmset 是用于管理电源设置的强大工具&#xff0c;我们将使用这个命令 &#xff08;1&#xff09;查询当前任务 pmset -g sched查看到我当前的设置是 唤醒电源开启在 工作日的每天早上8点半 上班时不用手动开机了 &#xff08;2&#xff09;删…

瀚高创库建表pgsql

1.瀚高下载地址&#xff1a; 下载 (highgo.com)https://www.highgo.com/down_main.html 2.瀚高linux安装 上传deb文件到ubuntu系统中 执行 dpkg -i hgdb-see-4.5.8-fe4791c.x86_64.deb 命令安装数据库 安装完成后&#xff0c;会在/opt 目录下生成安装目录 数据库安装完毕后…

力扣--LCR 150.彩灯装饰记录II

题目 代码 if(root null){ return new ArrayList<>(); } Queue<TreeNode> queue new LinkedList<>();List<List<Integer>> res new ArrayList<>();queue.add(root);while(!queue.isEmpty()){int k queue.size();List<Integer> …

ubuntu24.04安装Kubernetes1.31.0(k8s1.30.0)高可用集群

ubuntu24.04安装Kubernetes1.30.0(kubernetes1.30.0)高可用集群 一、总体概览 目前最新版的K8S版本应该是1.31.0,我们安装的是第二新的版本1.30.0,因为有大神XiaoHH Superme指路,所以基本上没踩坑,很顺利就搭建完成了。所有的机器都采用的最新版Ubuntu-Server-24.04长期支…

由于导包而引发的错误

今天在调试时发现删除功能无论如何都无法实现&#xff0c;于是调试找到了mapper层的错误但不知道为什么报错。以下是报错信息。 Caused by: org.apache.ibatis.binding.BindingException: Parameter userIds not found. Available parameters are [arg0, collection, list]at o…

结构体,枚举,联合知识点笔记总结

结构体&#xff1a; 1.之前我们知道&#xff0c;数组&#xff1a;一些值的结合&#xff0c;类型是相同的 结构&#xff1a;是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量 struct s {int a; --|-->结构体成员int b; --}; 注意…

HTML飞舞的爱心(完整代码)

写在前面 HTML语言实现飞舞的爱心完整代码。 完整代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><title>飞舞爱心</title><style>* {margin: 0;padding: 0;}html,body {overflow: hidd…

数据结构--数组

目录 1 定义 1.1 数组内存结构 1.2二维数组 2 练习 2.1 将数组内两个区间内有序元素合并 2.2 leetcode88. 合并两个有序数组 3 缓存与局部性原理 1 定义 1.1 数组内存结构 1 2 3 5 6 给数组添加元素时&#xff0c;应将原来添加位置的元素和之后的元素进行复制 System…

【接口自动化测试】一文从3000字从0到1详解接口测试用例设计

接口自动化测试是软件测试中的一种重要手段&#xff0c;它能有效提高测试效率和测试覆盖率。在进行接口自动化测试之前&#xff0c;首先需要进行接口测试用例的设计。本文将从0到1详细且规范的介绍接口测试用例设计的过程&#xff0c;帮助读者快速掌握这一技能。 一、了解接口…

麒麟系统x86安装达梦数据库

一、安装准备前工作 操作系统&#xff1a;银河麒麟V10&#xff0c;CPU&#xff1a; x86_64 架构 下载地址&#xff0c;麒麟官网&#xff1a;https://www.kylinos.cn/ 数据库&#xff1a;dm8_20220915_x86_kylin10_64 下载地址&#xff0c;达梦数据库官网&#xff1a;https://…

个人博客接入github issue风格的评论,utteranc,gitment

在做个人博客的时候&#xff0c;如果你需要评论功能&#xff0c;但是又不想构建用户体系和评论模块&#xff0c;那么可以直接使用github的issue提供的接口&#xff0c;对应的开源项目有utteranc和gitment&#xff0c;尤其是前者。 它们的原理是一样的&#xff1a;在博客文章下…

6.算法移植第六篇 YOLOV5/rknn生成可执行文件部署在RK3568上

接上一篇文章best-sim.rknn模型生成好后&#xff0c;我们要将其转换成可执行文件运行在RK3568上&#xff0c;这一步需要在rknpu上进行&#xff0c;在强调一遍&#xff01;&#xff01;rknpu的作用是可以直接生成在开发板上运行的程序 退出上一步的docker环境 exit1.复制best-…

PyMOL操作手册

PyMOL 操作手册 The man will be silent, the woman will be tears. – itwangyang ​ 翻译整理&#xff1a;itwangyanng 2024 年 11月 29 日 目录 初识 PyMOL… 5 0.1 安装 PyMOL… 5 0.1.1 Windows 系统开源版 PyMOL 的安装… 5 0.1.2 教育版 PyMOL 的下载安装……

HarmonyOS Next 模拟器安装与探索

HarmonyOS 5 也发布了有一段时间了&#xff0c;不知道大家实际使用的时候有没有发现一些惊喜。当然随着HarmonyOS 5的更新也带来了很多新特性&#xff0c;尤其是 HarmonyOS Next 模拟器。今天&#xff0c;我们就来探索一下这个模拟器&#xff0c;看看它能给我们的开发过程带来什…

Flink 从入门到实战

Flink中的批和流 批处理的特点是有界、持久、大量&#xff0c;非常适合需要访问全部记录才能完成的计算工作&#xff0c;一般用于离线统计。 流处理的特点是无界、实时, 无需针对整个数据集执行操作&#xff0c;而是对通过系统 传输的每个数据项执行操作&#xff0c;一般用于实…

HarmonyOS 5.0应用开发——列表(List)

【高心星出品】 文章目录 列表&#xff08;List&#xff09;列表介绍列表布局设置主轴方向设置交叉轴方向 列表填充分组列表填充 滚动条位置设置滚动位置滚到监听 列表项侧滑 列表&#xff08;List&#xff09; 列表介绍 列表作为一种容器&#xff0c;会自动按其滚动方向排列…

RBF神经网络预测结合NSGAII多目标优化

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 RBF神经网络预测结合NSGAII多目标优化 rbf神经网络预测结合nsga2多目标优化 题外话&#xff1a; 多目标优化是指在优化问题中同时考虑多个目标函数的优化过程。在多目标优化中&#xff0c;通常存在多个冲突的目标&am…

HTTPTomcatServlet

今日目标: 了解JavaWeb开发的技术栈理解HTTP协议和HTTP请求与响应数据的格式掌握Tomcat的使用掌握在IDEA中使用Tomcat插件理解Servlet的执行流程和生命周期掌握Servlet的使用和相关配置1,Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网,也称为万维网(www),能够通过浏览…