设计模式-职责链模式

文章目录

  • 职责链模式
    • 模式概述
    • 主要角色
    • 适用场景
    • 实现步骤
    • 优点
    • 注意事项
  • 定义
  • 职责链结构
  • 示例
  • 总结

职责链模式

职责链模式是一种行为设计模式,它可以将请求的发送者和请求的处理者解耦,并按照预定义的顺序处理请求。职责链模式常用于需要逐级审批或转交处理的场景。

模式概述

职责链模式通过建立一个处理请求的对象链(职责链),将发送者和处理者分离开来。请求沿着职责链依次传递,直到有一个处理者能够处理它为止。这样,请求的发送者不需要知道哪个具体对象会处理请求,而处理者也不需要知道请求的发送者是谁。

主要角色

  • 抽象处理者(Handler):定义了处理请求的接口,并可以设定继任者(successor)。
  • 具体处理者(ConcreteHandler):实现抽象处理者的接口,根据自身的能力判断是否可以处理请求,如果可以则进行处理,否则将请求转发给继任者。

适用场景

适用于以下情况:

  • 系统中存在多个对象可以处理同一请求,但具体处理者在运行时才能确定。
  • 发送者和接收者之间的耦合关系需要降低。
  • 需要动态指定处理链的顺序或配置处理链。

实现步骤

  1. 定义抽象处理者,声明处理请求的方法,并提供设置继任者的方法。
  2. 实现具体处理者,根据自身的能力判断是否能够处理请求,如果可以则进行处理,否则将请求转发给继任者。
  3. 在客户端中创建处理链,并按照预定顺序设置继任者关系。
  4. 将请求发送到处理链的起始点,让处理链逐级处理请求。

优点

  • 解耦了请求的发送者和处理者,增强了系统的灵活性和可维护性。
  • 动态配置处理链,可以灵活地改变请求的处理顺序或增减处理者。
  • 符合单一职责原则和开闭原则。

注意事项

  • 需要正确设置处理链的顺序,确保请求能够被正确处理。
  • 处理链的最后一个处理者必须能够处理所有未被前面的处理者处理的请求,避免请求无法得到处理。

职责链模式可以简化请求的发送和处理过程,提高系统的灵活性和可扩展性。但需要合理设计和配置处理链,以确保请求能够被正确处理。

参考资料:《设计模式:可复用面向对象软件的基础》(GoF)

定义

职责链模式是一种行为设计模式,用于将请求的发送者和请求的处理者解耦,并且能够按照预定义的顺序处理请求。通过职责链模式,处理者负责处理请求,而客户只需将请求发送到职责链上,无需关心请求的处理细节和传递过程。

职责链结构

职责链模式的主要结构包括抽象处理者(Handler)和具体处理者(ConcreteHandler)。抽象处理者定义了一个处理请求的接口,并且可以设定继任者(successor)。具体处理者实现了抽象处理者的接口,并根据自身的能力来判断是否能够处理请求,如果可以处理则进行处理,否则将请求传递给继任者。
在这里插入图片描述

示例

以下是一个简单的职责链模式示例的代码:

// 设置处理请求的抽象类
abstract class Handler
{
    protected Handler successor;

    // 设置继任者
    public void SetSuccessor(Handler successor)
    {
        this.successor = successor;
    }

    // 处理请求的抽象方法
    public abstract void HandleRequest(int request);
}

// 具体处理者类
class ConcreteHandler1 : Handler
{
    public override void HandleRequest(int request)
    {
        if (request >= 0 && request < 10)
        {
            Console.WriteLine("{0} 处理请求 {1}", this.GetType().Name, request);
        }
        else if (successor != null)
        {
            // 请求传递给继任者
            successor.HandleRequest(request);
        }
    }
}

// 其他具体处理者类与第一个类似,范围不同

// 客户端代码
static void Main(string[] args)
{
    Handler h1 = new ConcreteHandler1();
    Handler h2 = new ConcreteHandler2();
    Handler h3 = new ConcreteHandler3();

    h1.SetSuccessor(h2); // 设置继任者
    h2.SetSuccessor(h3);

    int[] requests = { 2, 4, 5, 7, 8, 12, 23, 27, 6 };
    foreach (int request in requests)
    {
        h1.HandleRequest(request);
    }

    Console.Read();
}

在这里插入图片描述这段代码是一个简单的职责链模式的实现示例。以下是对这个代码的一些要点解释和改进建议:

  1. 职责链的顺序设置:在当前的代码中,通过SetSuccessor()方法手动设置了处理链的顺序。这种硬编码方式不够灵活,如果需要动态地配置处理链的顺序,可能需要修改代码。可以考虑使用其他方式,比如配置文件或依赖注入,从而实现更灵活的处理链配置。

  2. 请求的范围判断:在具体处理者类中,使用了一个条件判断语句来确定是否能够处理请求。目前的实现中,每个具体处理者都需要实现相同的条件判断逻辑,这样会导致代码重复。可以考虑将请求的范围判断逻辑抽离出来,单独封装成一个工具类或方法,让具体处理者直接调用,避免代码重复。

  3. 继任者的处理:当前的代码中,当具体处理者无法处理请求时,会将请求传递给继任者。这种方式可以确保请求能够被处理,但可能存在一个问题:如果继任者也无法处理请求,请求会一直传递下去直到最后一个处理者。为了避免请求无限传递,可以考虑在最后一个处理者中添加一个默认的处理逻辑,比如抛出一个异常或给出一个默认的处理结果。

  4. 扩展性和灵活性:职责链模式的一个重要特点是扩展性和灵活性。当前的代码通过继承和设置继任者的方式实现了处理链,这样可以方便地添加新的处理者并灵活调整处理顺序。但在实际应用中,可能还需要考虑更复杂的场景,比如动态添加、删除和调整处理者等。可以根据具体需求进行扩展和改进。

  5. 错误处理和异常处理:在当前的代码中,并没有专门处理处理请求时可能出现的错误或异常情况。为了提高代码的健壮性,可以在处理请求时添加适当的错误处理和异常处理机制,以确保系统的稳定性和可靠性。

在上述示例中,根据请求的大小范围,具体处理者对象判断是否可以处理该请求。如果可以处理,则进行处理;如果不能处理,则将请求传递给继任者进行处理。这样的处理过程可以按照设置好的顺序依次执行。

总结

职责链模式的优点包括解耦请求发送者和处理者、动态配置处理链、增强系统的灵活性和可扩展性等。但需要注意的是,如果没有正确配置处理链或最后一个处理者无法处理请求,请求可能无法得到处理。

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

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

相关文章

根据源码,模拟实现 RabbitMQ - 网络通讯设计,自定义应用层协议,实现 BrokerServer (8)

目录 一、网络通讯协议设计 1.1、交互模型 1.2、自定义应用层协议 1.2.1、请求和响应格式约定 ​编辑 1.2.2、参数说明 1.2.3、具体例子 1.2.4、特殊栗子 1.3、实现 BrokerServer 1.3.1、属性和构造 1.3.2、启动 BrokerServer 1.3.3、停止 BrokerServer 1.3.4、处…

PHP8函数的引用和取消-PHP8知识详解

今天分享的是php8函数的引用和取消&#xff0c;不过在PHP官方的参考手册中&#xff0c;已经删除了此类教程。 1、函数的引用 在PHP8中不管是自定义函数还是内置函数&#xff0c;都可以直接简单的通过函数名调佣。函数的引用大致有下面3种&#xff1a; 1.1、如果是PHP的内置函…

Docker - Docker安装MySql并启动

因为项目需要连接数据库&#xff0c;但是远程服务器上的mysql我不知道账户和密码&#xff0c;这个时候便是docker发挥作用的关键时刻了&#xff01; 目录 docker安装安装gcc卸载老docker&#xff08;如有&#xff09;安装软件包设置镜像仓库更新yum软件包索引安装docker启动doc…

ESP32-CAM模块Arduino环境搭建测试

ESP32-CAM模块Arduino环境搭建测试 一.ESP32OV2640摄像头模块CameraWebServer视频查看 二.测试ESP32-CAM(后续称cam模块)代码是否上传执行成功测试 const int led0 12; const int led1 13;void setup() {// put your setup code here, to run once:pinMode(led0, OUTPUT);pin…

【业务功能篇84】微服务SpringCloud-ElasticSearch-Kibanan-电商实例应用

一、商品上架功能 ElasticSearch实现商城系统中全文检索的流程。 1.商品ES模型 商品的映射关系 PUT product {"mappings": {"properties": {"skuId": {"type": "long"},"spuId": {"type": "ke…

前端vue引入高德地图入门教程

距离上一篇关于前端项目中使用高德地图的文章已经将近5年之久&#xff0c; 这是我的第一篇关于高德地图的文章 这期间前端技术日新月异&#xff0c;5年前JQuery还如日中天&#xff0c;如今已经销声匿迹&#xff0c;很少有公司招聘还在要求JQuery&#xff0c;更多的是Vue、React…

Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required

项目场景&#xff1a; 最近因为公司业务需要在搭一个新架构&#xff0c;用的springboot3和jdk17,在整合mybatis多数据源的时候报错 &#xff08;引用的mybatisplus 和 mybatisplusjion的是最新的包-2023-08-26&#xff09; Error creating bean with name ‘XXXServiceImpl’:…

非煤矿山风险监测预警算法 yolov8

非煤矿山风险监测预警算法通过yolov8网络模型深度学习算法框架&#xff0c;非煤矿山风险监测预警算法在煤矿关键地点安装摄像机等设备利用智能化视频识别技术&#xff0c;能够实时分析人员出入井口的情况&#xff0c;人数变化并检测作业状态。YOLO的结构非常简单&#xff0c;就…

【八股】2023秋招八股复习笔记5(计算机网络-CN)

文章目录 八股目录目录1、应用层 & HTTP一些http题HTTPS 加密原理&#xff08;问过&#xff09;HTTP/1.1 新特性HTTP/2.0 与 RPC&#xff08;问过&#xff09;GET 和 POST 比较 2、传输层 & TCPTCP三次握手 & 四次挥手&#xff08;问过&#xff09;为什么每次TCP 连…

118.杨辉三角

一、题目 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 二、代码 class Solution { public:vector<vector<int>> generate(int numRows) {vector<vector<int>>data(numRows);for(int i0;i<numRows;i){data[i].resize(i1);//扩容data[i]…

一文读懂 KubeSphere 企业版 4.0:多品类生态价值赋能的里程碑

近日&#xff0c;青云科技 KubeSphere 团队革新先行&#xff0c;重磅发布了沉淀数年、倾力打造的全新分布式云原生可扩展开放架构——KubeSphere LuBan&#xff0c;以及在此之上构建的化整为零、全能开放、随时随地自由集成的云原生操作系统——KubeSphere 企业版 (KubeSphere …

QTday1(第一个QT界面、常用类与组件)

一、Xmind整理&#xff1a; Assistant帮助文档的使用&#xff1a; 设计师界面的介绍&#xff1a; 各文件之间调用方式&#xff1a; 二、上课笔记整理&#xff1a; 1.第一个QT界面 ①创建自定义类时需要指定父类 ②第一个界面的相关操作 #include "mainwindow.h"…

基于MYSQL的主从同步和读写分离

目录 一.完成MySQL主从同步&#xff08;一主两从&#xff09; 1.主库配置 2.建立同步账号 3.锁表设置只读 4.备份数据库数据 5.主库备份数据上传到从库 6.从库上还原备份 7.解锁 8.从库上设定主从同步 9.启动从库同步开关 10.检查状态 二.基于MySQL一主两从配置&…

LabVIEW | 串口基础【自学】

转载 B站   up&#xff1a;不烧板子 地址&#xff1a;https://www.bilibili.com/read/cv9435378 原博图片不清楚&#xff0c;自己重新跟学截图自留&#xff0c;侵删 文章目录 一、串口基础1.串口发送&#xff08;1&#xff09;简单发送&#xff08;2&#xff09;循环发送&…

【深度学习 | 核心概念】那些深度学习路上必经的核心概念,确定不来看看?(二)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

[JDK8下的HashMap类应用及源码分析] 数据结构、哈希碰撞、链表变红黑树

系列文章目录 [Java基础] StringBuffer 和 StringBuilder 类应用及源码分析 [Java基础] 数组应用及源码分析 [Java基础] String&#xff0c;分析内存地址&#xff0c;源码 [JDK8环境下的HashMap类应用及源码分析] 第一篇 空构造函数初始化 [JDK8环境下的HashMap类应用及源码分…

LeetCode-160. 相交链表

这是一道真的非常巧妙的题&#xff0c;题解思路如下&#xff1a; 如果让他们尾端队齐&#xff0c;那么从后面遍历就会很快找到第一个相交的点。但是逆序很麻烦。 于是有一个巧妙的思路诞生了&#xff0c;如果让短的先走完自己的再走长的&#xff0c;长的走完走短的&#xff0c;…

关于商品活动的H5页面技术总结

背景 在单个html文件里面使用vue3、jquery等其他第三方js库&#xff0c;实现规定的页面效果&#xff0c;其中主要功能是从商品json数据中读取数据&#xff0c;然后可以通过搜索框、下拉框、左侧菜单来筛选商户信息。 页面布局 技术要点&#xff1a; 1、通过路由来进行页面布…

Visual Studio 2022的MFC框架——AfxWinMain全局对象和InitInstance函数

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 在看这篇帖子前&#xff0c;请先看我的另一篇帖子《Visual Studio 2022的MFC框架——应用程序向导》。 当程序调用了CWinApp类的构造…

goroutine的一点东西

前面的两篇&#xff0c;从相对比较简单的锁的内容入手(也是干货满满)&#xff0c;开始了go的系列。这篇开始&#xff0c;进入更核心的内容。我们知道&#xff0c;go应该是第一门在语言层面支持协程的编程语言(可能是我孤陋寡闻)&#xff0c;goroutine也完全算的上是go的门面。g…