15行为型设计模式——责任链模式

news2024/9/21 9:51:10

一、责任链模式简介

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,也叫职责链模式或者职责连锁模式。用于处理请求的多个对象,以实现请求的分发和处理。它的核心思想是将请求的处理职责链式地传递给多个对象中的一个或多个,从而避免请求发送者和接收者之间的耦合。该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作责任链模式。责任链的形式在我们的日常工作和生活中处处可见。

工作、生活中的责任链模式

例1:客户Client有一个买车的需求,这个需求对客户来说就一个买车,但是对4S店或者汽车销售商来说有试驾车辆、交钱、签立合同、交接车钥匙四个部分。 首先客户Client和销售谈,客户Client试驾车辆满意后,把任务交给财务,客户Client付完余款之后,把任务交给法务,客户Client签完合同按手印之后,把任务交给车钥匙保管员,客户Client无悲无喜的拿到车钥匙走人。

例2:政府某部门的某项工作,县政府某部门先完成自己能处理的任务,不能处理的任务交给省政府某部门,省政府某部门再完成自己职责范围内的任务,不能处理的任务交给中央政府某部门,中央政府某部门最后完成该项工作的审批。

例3:某家庭分工合作缩短出游时间,某天当即出发前往明秀山川旅游,妈妈二话不说接下导游的任务,制作旅游攻略,爸爸沉默不语去了趟超市买生活用品和医用急救品,女儿贴心的备好换洗衣服和防晒霜,至于儿子负责宣传一家人出游的消息,让街坊四邻一顿羡慕+短时间内不打扰他家幸福生活。

 责任链模式的结构图

主要组成部分

  1. 处理者(Handler):定义一个处理请求的接口,并实现具体的处理逻辑。每个处理者对象都持有对下一个处理者对象的引用。
  2. 具体处理者(ConcreteHandler):实现处理者接口,并具体实现请求处理的逻辑。如果无法处理请求,它将请求转发给下一个处理者。
  3. 客户端(Client):创建具体的处理者对象,并设置责任链的顺序。然后,向链中的第一个处理者发送请求。

工作流程

  1. 客户端将请求发送到责任链中的第一个处理者。
  2. 第一个处理者处理请求,如果不能处理,便将请求传递给下一个处理者。
  3. 这个过程会一直持续下去,直到请求被处理或者链中的所有处理者都没有处理请求。

责任链模式的应用场景

1. 日志记录

在日志记录系统中,通常需要将日志记录到不同的目标(如文件、控制台、网络等)。通过使用责任链模式,可以将日志记录处理分为不同的处理者,每个处理者负责不同的日志记录策略。例如,可以先将日志记录到文件中,如果写入失败,再尝试写入控制台等。

2. 权限检查

在安全系统中,权限检查通常涉及多个权限层级。责任链模式可以用来处理权限检查请求,依次检查各个权限层级,确保用户具有足够的权限来执行某个操作。

3. 消息处理

在消息处理系统中,消息可能需要经过多个处理阶段,例如解析、验证、转换和存储。使用责任链模式可以将这些处理阶段链式地组织起来,简化消息处理流程的管理。

4. 输入验证

在表单输入验证中,通常需要进行多种检查,例如格式检查、范围检查和依赖检查。责任链模式可以将这些检查逻辑分成不同的处理者,逐个处理输入验证,直到输入符合要求或所有检查都失败。

5. 任务处理

在任务处理系统中,任务可能需要经过多个步骤的处理,例如数据预处理、核心处理和结果后处理。使用责任链模式可以将这些步骤分开,实现任务的逐步处理。

6. 用户请求处理

在Web应用程序中,用户请求通常需要经过多个过滤器和处理器,例如认证、授权、请求预处理和响应后处理。责任链模式可以有效地组织这些处理步骤,确保请求按照预定的顺序得到处理。

7. 图形界面事件处理

在图形用户界面(GUI)框架中,事件处理(如鼠标点击、键盘输入)通常需要经过多个事件处理器。责任链模式可以将这些处理器按顺序组织起来,使得事件可以在处理链中被逐个处理。

8. 动态配置

在动态配置系统中,配置可能需要经过多个处理器进行解析和验证。责任链模式可以使得这些处理器按顺序处理配置项,并提供灵活的配置处理机制。

二、责任链模式的设计方法

 chain.cpp

#include <iostream>

// 处理者接口
class Handler {
public:
    virtual ~Handler() {}
    virtual void setNext(Handler*) = 0;
    virtual void handle(const std::string& request) = 0;
};

// 具体处理者:试驾车辆
class TestDriveHandler : public Handler {
public:
    void setNext(Handler* next) override {
        next_ = next;
    }

    void handle(const std::string& request) override {
        if (request == "试驾车辆") {
            std::cout << "这辆车试驾体验good nice!" << std::endl;
        } else if (next_ != nullptr) {
            next_->handle(request);
        }
    }

private:
    Handler* next_;
};

// 具体处理者:交钱
class PaymentHandler : public Handler {
public:
    void setNext(Handler* next) override {
        next_ = next;
    }

    void handle(const std::string& request) override {
        if (request == "交钱") {
            std::cout << "您账户9999于某年某月某日入账亿亿宇宙币." << std::endl;
        } else if (next_ != nullptr) {
            next_->handle(request);
        }
    }
    
private:
    Handler* next_;
};

// 具体处理者:签合同
class SignContractHandler : public Handler {
public:
    void setNext(Handler* next) override {
        next_ = next;
    }

    void handle(const std::string& request) override {
        if (request == "签合同") {
            std::cout << "什么年代了,还按手印啊,无语,手印按好了!" << std::endl;
        } else if (next_ != nullptr) {
            next_->handle(request);
        }
    }
    
private:
    Handler* next_;
};

// 具体处理者:交接车钥匙
class HandoverKeyHandler : public Handler {
private:
    Handler* next_;

public:
    void setNext(Handler* next) override {
        next_ = next;
    }

    void handle(const std::string& request) override {
        if (request == "交接车钥匙") {
            std::cout << "先生/女士,请拿好您的车钥匙" << std::endl;
        } else if (next_ != nullptr) {
            next_->handle(request);
        }
    }
};

void doWorking() {
    // 设置处理链
    Handler* testDrive = new TestDriveHandler;
    Handler* payment = new PaymentHandler;
    Handler* signContract = new SignContractHandler;
    Handler* handoverKey = new HandoverKeyHandler;

    testDrive->setNext(payment);
    payment->setNext(signContract);
    signContract->setNext(handoverKey);

    // 客户请求
    testDrive->handle("试驾车辆");
    testDrive->handle("交钱");
    testDrive->handle("签合同");
    testDrive->handle("交接车钥匙");

    // 释放资源
    delete handoverKey;
    delete signContract;
    delete payment;
    delete testDrive;
    return ;
}

int main() {
	doWorking();
	return 0;
}

运行效果

三、总结

优点
  • 降低耦合度:请求发送者和请求处理者之间不需要直接联系,通过责任链传递请求,解耦了发送者和处理者。
  • 动态处理:可以动态地改变处理者链的顺序。
  • 增强扩展性:增加新的处理者时,只需添加新处理者而不需修改现有的处理者代码。
缺点
  • 不保证请求被处理:如果责任链的最后一个处理者不能处理请求,请求可能会被丢弃。
  • 链的配置可能复杂:管理和配置处理者链可能会变得复杂,特别是在处理者数量较多时。

责任链模式中每一个类只需要负责自己的任务,不属于自己的任务则交给其他链上的类。链上的每一个类或组合类的相邻链之间由上一个链上的类触发下一个链上的类(抽象接口Handler帮忙)。多个链上的类组合一起最终完成一个被拆解的复杂的需求。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NRP-Z24功率探头RS/NRP-Z23详情参数NRP-Z21功率传感器

USB 功率传感器&#xff1a; NRP-Z11 频率范围&#xff1a;10 MHz - 8 GHz 功率范围&#xff1a;-67 dBm to 23 dBm. NRP-Z21 频率范围&#xff1a;10 MHz - 18 GHz 功率范围&#xff1a;-67 dBm to 23 dBm. NRP-Z22 频率范围&#xff1a;10 MHz - 18 GHz 功率范围&#xff…

Java:简述类的加载机制-双亲委派

类加载的机制过程分为以下&#xff1a;加载、验证、准备、解析、初始化等。 在第一步的加载环节&#xff0c;Java类加载器有四种&#xff1a;Bootstrap类加载器、Extention 类加载器、Application类加载器、Custom自定义类加载器&#xff0c;其中会涉及“双亲委派”模式。 一…

Linux 安装Mysql保姆级教程

一、检查环境 我们登录服务器,查看之前是否安装过mysql rpm -qa | grep mysql 由于我之前安装过,所以这里是有数据的 如果需要删除重新下载,可以使用 rpm -e mysql57-community-release-el7-10.noarch.rpm 二、安装 1、下载 接下来下载安装包 wget -i -c http:/…

CAM Back Again论文详解

论文名称&#xff1a;Large Kernel CNNs from a Weakly Supervised ObjectLocalization Perspective 论文地址&#xff1a;[2403.06676] CAM Back Again: Large Kernel CNNs from a Weakly Supervised Object Localization Perspective (arxiv.org) 出发点 据报道&#xff0c…

通配符证书的简介和申请方法

通配符证书是一种SSL证书&#xff0c;它利用域名字段中的通配符&#xff08;*&#xff09;来指示&#xff0c;允许用户在一个证书中关联多个顶级域名及其子域&#xff0c;从而简化证书管理流程&#xff0c;节省成本和时间。以下是通配符证书的简介和申请方法的详细说明&#xf…

微信小程序开发--详情【开发一次 多端覆盖】

目录 1、准备工作 了解 uni-app : 准备开发工具&#xff1a; 下载 &#xff1a; 安装完成后&#xff0c;打开这个开发者工具&#xff1a; 对微信小程序进行配置&#xff1a; 使用开发工具HBuilderX:&#xff1a; 先安装终端插件 2、初始化一个demo 创建项目&#xff1…

分类预测|基于麻雀优化核极限学习机的数据分类预测Matlab程序SSA-KELM 多特征输入多类别输出 含基础KELM

分类预测|基于麻雀优化核极限学习机的数据分类预测Matlab程序SSA-KELM 多特征输入多类别输出 含基础KELM 文章目录 前言分类预测|基于麻雀优化核极限学习机的数据分类预测Matlab程序SSA-KELM 多特征输入多类别输出 含基础KELM 一、SSA-KELM模型SSA-KELM 分类预测的详细原理和流…

软考 -- 软件设计师 -- 二轮复习(1) -- 计算机系统基础知识错题集和重点知识(持续更新)

软考 – 软件设计师 – 二轮复习(1) – 计算机系统基础知识错题集和重点知识(持续更新) 文章目录 软考 -- 软件设计师 -- 二轮复习(1) -- 计算机系统基础知识错题集和重点知识(持续更新)前言一、CPU二、内存编址计算三、原码、反码、补码、移码计算四、浮点数 前言 考试时间&a…

led台灯对眼睛好不好?护眼台灯怎么选对眼睛好?收下这份攻略

随着年级的升高与学业内容的日益丰富&#xff0c;学生们待在书桌前的时间却越来越长。同时电子产品的广泛普及&#xff0c;让我国青少年的用眼负担显著增加。权威机构预测&#xff0c;到2050年&#xff0c;全球近视人群将达到惊人的49.49亿人&#xff0c;患病率高达52%。这一严…

MySQL编译安装

1.源码包地址 2.编译/安装 3.设置环境变量 4.初始化/登录 地址: MYSQL源码包下载 右键复制链接 使用wget 下载到/usr/local/src下 再使用rpm –ivh 安装 --这个时候跳转到 cd /root/rpmbuild/SOURCES 使用ll查看有什么东西 yum -y install gcc gcc-c ncurses ncurses-d…

java设计模式day01--(类之间的关系、软件设计原则、单例设计模式)

视频网址&#xff1a;s1.设计模式-课程介绍_哔哩哔哩_bilibili 1&#xff0c;设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中&#xff0c;而是被用于建筑领域的设计中。 1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构…

Apache RocketMQ 批处理模型演进之路

作者&#xff1a;谷乂 RocketMQ 的目标&#xff0c;是致力于打造一个消息、事件、流一体的超融合处理平台。这意味着它需要满足各个场景下各式各样的要求&#xff0c;而批量处理则是流计算领域对于极致吞吐量要求的经典解法&#xff0c;这当然也意味着 RocketMQ 也有一套属于自…

ImportError: DLL load failed while importing _wrapper: 找不到指定的模块

今天使用pyinstaller打包好脚本,执行打包好的程序后,出现如下的报错: 这个问题花了我一个上午,在网上查找相关的解决方法,然而不知道是我的搜索方式有问题,还是这个资料比较少,找了很久,只找到了一篇极度相关的文章:https://blog.csdn.net/weixin_46457351/article/d…

C Primer Plus第十五章编程练习,仅供参考

第十五章编程练习 本章第一个编程练习的内容是让我们将二进制字符串转换为一个数值&#xff0c;传递字符串指针&#xff0c;逻辑并不复杂&#xff0c;完整程序代码以及运行结果如下&#xff1a; #include<stdio.h> #include<string.h> #include<math.h> in…

从C向C++28——设计模式

一.设计模式 1.设计模式理解 ​ C程序设计模式是针对在C编程中常见问题的通用、可重用的解决方案。设计模式主要是在软件工程领域&#xff0c;特别是在面向对象编程中发展起来的&#xff0c;它们提供了一种标准的术语和解决方案&#xff0c;可以帮助程序员更好地设计软件架构…

豆包 MarsCode试用体验

1.前言 豆包 MarsCode 是一款为你提供了AI编程助手和云端集成开发环境来协助你完成编程任务的产品。 2.功能介绍 2.1.豆包 MarsCode 编程助手 豆包 MarsCode 编程助手是豆包旗下的 AI 编程助手&#xff0c;提供以智能代码补全为代表的 AI 功能。它支持主流的编程语言和 IDE…

Luma AI,让你的视频像电影一样精彩!附带使用教程

Luma 视频生成 API 对接说明 随着 AI 的应用变广&#xff0c;各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多&#xff0c;从最初的写作&#xff0c;到医疗教育&#xff0c;再到现在的视频。 Luma 是一个专业高质量的视频生成平…

tomcat实验

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;Tomcat 具有处理HTML页面的功能&#xff0c;它还是一个Servlet和JSP容器。 下载文件 安装javajdk 解压 …

ComfyUI基础操作教学!小白入门必看!

在我们打开comfyui后会面对一堆节点&#xff0c;那么这些节点都是什么意思呢&#xff1f;今天跟着小元老师来学习一下吧&#xff5e; 一、拆解文生图基本工作流 这个是Comfyui默认的文生图工作流它的基本逻辑是&#xff1a; 条件输入板块——潜空间——像素空间 01 条件输入模…

AiThinkerIDE_V1.5.2工程随意移动地方,路径不能有空格

路径不能有空格&#xff0c;例如usr_sdk不能改为usr sdk IDF_PATH&#xff1a; ${workspace_loc:/AiThinkerProjectForESP}${workspace_loc:/AiThinkerProjectForESP}/examples/get-started/hello_world