C++ 设计模式之责任链模式

【声明】本题目来源于卡码网(卡码网KamaCoder)

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分


设计模式大纲】


【简介】

        --什么是责任链模式(第21种设计模式)

        责任链模式是⼀种行为型设计模式,它允许你构建⼀个对象链,让请求从链的⼀端进⼊,然后沿着链上的对象依次处理,直到链上的某个对象能够处理该请求为止。

        职责链上的处理者就是⼀个对象,可以对请求进⾏处理或者将请求转发给下⼀个节点,这个场景在⽣活中很常⻅,就是⼀个逐层向上递交的过程,最终的请求要么被处理者所处理,要么处理不了,这也因此可能导致请求⽆法被处理。


 【组成结构】

        责任链模式包括以下几个基本结构:

  • 1. 处理者Handler :定义⼀个处理请求的接⼝,包含⼀个处理请求的抽象⽅法和⼀个指向下⼀个处理者的链接。
  • 2. 具体处理者ConcreteHandler : 实现处理请求的⽅法,并判断能否处理请求,如果能够处理请求则进⾏处理,否则将请求传递给下⼀个处理者。
  • 3. 客户端:创建并组装处理者对象链,并将请求发送到链上的第⼀个处理者


 【简易实现 - Java】

        以Java代码作以简要说明

1. 处理者

        定义处理请求的接口

interface Handler {
    // 处理请求的⽅法
    void handleRequest(double amount);
    // 设置下⼀个处理者的⽅法
    void setNextHandler(Handler nextHandler);
}

2. 具体处理者

        实现处理请求

class ConcreteHandler implements Handler {
    private Handler nextHandler;

    @Override
    public void handleRequest(Request request) {
        // 根据具体情况处理请求,如果⽆法处理则交给下⼀个处理者
        if (canHandle(request)) {
            // 处理请求的逻辑
        } else if (nextHandler != null) {
            // 交给下⼀个处理者处理
            nextHandler.handleRequest(request);
        } else {
            // ⽆法处理请求的逻辑
        }
    }

    @Override
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 具体处理者⾃⼰的判断条件
    private boolean canHandle(Request request) {
        // 根据具体情况判断是否能够处理请求
        return /* 判断条件 */;
    }
}

3. 客户端

        创建并组装处理者对象链,将请求发送给链上第⼀个处理者

public class Main {
    public static void main(String[] args) {
        // 创建处理者实例
        Handler handler1 = new ConcreteHandler();
        Handler handler2 = new ConcreteHandler();
        // ...
        // 构建责任链
        handler1.setNextHandler(handler2);
        // ...
        // 发送请求
        Request request = new Request(/* 请求参数 */);
        handler1.handleRequest(request);
    }
}

【使用场景】

        责任链模式具有下⾯⼏个优点:

  • 降低耦合度:将请求的发送者和接收者解耦,每个具体处理者都只负责处理与⾃⼰相关的请求,客户端不需要知道具体是哪个处理者处理请求。
  • 增强灵活性:可以动态地添加或删除处理者,改变处理者之间的顺序以满⾜不同需求。

        但是由于⼀个请求可能会经过多个处理者,这可能会导致⼀些性能问题,并且如果整个链上也没有合适的处理者来处理请求,就会导致请求⽆法被处理。
        责任链模式是设计模式中简单且常⻅的设计模式,在⽇常中也会经常使⽤到,⽐如Java开发中过滤器的链式处理,以及Spring框架中的拦截器,都组装成⼀个处理链对请求、响应进⾏处理。


【C++编码部分】

1. 题目描述

        小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者,请你实现责任链模式,可以根据请求天数找到对应的处理者。

        审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。

2. 输入描述

        第一行是一个整数N(1 <= N <= 100), 表示请求申请的数量。接下来的N行,每行包括一个请求申请的信息,格式为"姓名 请假天数"。

3. 输出描述

        对于每个请假请求,输出一行,表示该请求是否被批准。如果被批准/否决,输出被哪一个职级的人批准/否决。

4. C++编程示例(可直接运行)

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file DutyChainMode.hpp
* @brief 责任链模式
* @autor 写代码的小恐龙er
* @date 2024/01/25
*/

#include <iostream>
#include <string>

using namespace std;

// 前置声明

// 用户请求类
class LeaveRequest;

//  处理者 接口类
class LeaveHandler;
// 具体处理者1 -- 主管(Supervisor) 3
class Supervisor;
// 具体处理者2 -- 经理(Manager) 7 
class Manager;
// 具体处理者3 -- 董事(Director) 10
class Director;

// 具体定义

// 用户请求类
class LeaveRequest
{
//成员数据
private:
    string _name;
    int _daysLeave = 0;
// 成员函数
public:
    //构造函数
    LeaveRequest(string name, int days){
        this->_name = name;
        this->_daysLeave = days;
    }
    // 成员数据获取接口
    string GetName(){
        return this->_name;
    }
    int GetDaysLeave(){
        return this->_daysLeave;
    }
};

//  处理者 接口类
class LeaveHandler
{
// 接口
public:
    virtual void HandleRequest(LeaveRequest *request) = 0;
};

// 具体处理者1 -- 主管(Supervisor) 3
class Supervisor : public LeaveHandler
{
//成员数据
private:
    const int _maxDays = 3;
    // 下一个处理者
    LeaveHandler *_nextHandler;
// 接口函数重载
public:
    // 构造函数
    Supervisor(){}
    Supervisor(LeaveHandler *nextHandler){
        this->_nextHandler = nextHandler;
    }
    void HandleRequest(LeaveRequest *request) override {
        if(request){
            if(request->GetDaysLeave() <= _maxDays){
                std::cout << request->GetName() << " Approved by Supervisor." << endl;
            }
            else if(_nextHandler){
                _nextHandler->HandleRequest(request);
            }
            else std::cout << request->GetName() << " Denied by Supervisor." << endl;
        }
    }
};

// 具体处理者2 -- 经理(Manager) 7 
class Manager : public LeaveHandler
{
//成员数据
private:
    const int _maxDays = 7;
    // 下一个处理者
    LeaveHandler *_nextHandler;
// 接口函数重载
public:
    // 构造函数
    Manager(){}
    Manager(LeaveHandler *nextHandler){
        this->_nextHandler = nextHandler;
    }
    void HandleRequest(LeaveRequest *request) override {
        if(request){
            if(request->GetDaysLeave() <= _maxDays){
                std::cout << request->GetName() << " Approved by Manager." << endl;
            }
            else if(_nextHandler){
                _nextHandler->HandleRequest(request);
            }
            else std::cout << request->GetName() << " Denied by Manager." << endl;
        }
    }
};

// 具体处理者3 -- 董事(Director) 10
class Director : public LeaveHandler
{
//成员数据
private:
    const int _maxDays = 10;
    // 下一个处理者
    const LeaveHandler *_nextHandler = nullptr;
// 接口函数重载
public:
    // 构造函数
    Director(){}
    // Director(LeaveHandler *nextHandler){
    //     this->_nextHandler = nextHandler;
    // }
    void HandleRequest(LeaveRequest *request) override {
        if(request){
            if(request->GetDaysLeave() <= _maxDays){
                std::cout << request->GetName() << " Approved by Director." << endl;
            }
            // else if(_nextHandler){
            //     _nextHandler->HandleRequest(request);
            // }
            else std::cout << request->GetName() << " Denied by Director." << endl;
        }
    }
};

int main()
{
    // 请求数量
    int requestNum = 0;
    std::cin >> requestNum;
    // 创建请求命令基类
    LeaveRequest *request = nullptr;
    // 创建处理者基类 -- 【创建处理流程时 也可单独创建一个类】
    LeaveHandler *director = new Director();
    LeaveHandler *manager = new Manager(director);
    LeaveHandler *supervisor = new Supervisor(manager);

    // 遍历
    for(int i = 0; i < requestNum; i++){
        // 请假者姓名 和 天数
        string name = "";
        int days = 0;
        // 输入
        std::cin >> name >> days;
        // 新建请求类
        request = new LeaveRequest(name, days);
        // 开始处理请求
        supervisor->HandleRequest(request);
    }
    
    //析构
    delete director;
    director = nullptr;

    delete manager;
    manager = nullptr;

    delete supervisor;
    supervisor = nullptr;
    
    if(request != nullptr){
        delete request;
        request = nullptr;
    }
    
    return 0;
}


......

To be continued.

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

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

相关文章

计算机工作原理解析和解剖(基础版)

我们会从软件⼯程师的⻆度解释计算机是如何⼯作的&#xff0c;我们的主要⽬标既不是期待 ⼤家可以造出⾃⼰的计算机&#xff0c;也不是介绍如何编程&#xff0c;⽽是希望让⼤家了解计算机的核⼼⼯作机制后&#xff0c;打破计算机的神秘感&#xff0c;并且有利于理解我们平时编程…

心理学大纲

简介 psychology&#xff0c;“psyche”(ψυχή):意为"soul"(灵魂)&#xff0c;即对我们灵魂的研究 我的学习的目的 了解人精神世界的模型&#xff0c;人格的形成]&#xff0c;作为观察分析他人内心的理论指导&#xff0c;便于我实践了解情绪的机理&#xff0c;…

vite项目创建

1.使用命令创建一个vite项目 npm init vuelatest vite.config.js配置 import { fileURLToPath, URL } from "node:url";import { defineConfig, loadEnv } from "vite"; import vue from "vitejs/plugin-vue"; export default defineConfig(({…

ZK监控方法以及核心指标

文章目录 1. 监控指标采集1.1 zk版本高于3.6.0监控指标采集1.2 zk版本低于3.6.0监控指标采集1.3 配置promethues采集和大盘 2. 核心告警指标3. 参考文章 探讨zk的监控数据采集方式以及需要关注的核心指标&#xff0c;便于日常生产进行监控和巡检。 1. 监控指标采集 3.6.0 版本…

哪吒汽车与经纬恒润合作升级,中央域控+区域域控将于2024年落地

近日&#xff0c;在2024哪吒汽车价值链大会上&#xff0c;哪吒汽车与经纬恒润联合宣布合作升级&#xff0c;就中央域控制器和区域域控制器展开合作&#xff0c;合作成果将在山海平台新一代车型上发布。 哪吒汽车首席技术官戴大力、经纬恒润副总裁李伟 经纬恒润在智能驾驶领域拥…

Java入门高频考查基础知识6-深入挖掘Java集合框架的奇幻世界(45题3.6万字参考答案)

在Java编程语言中&#xff0c;集合&#xff08;Collection&#xff09;指的是存储一组对象的容器。Java提供了一套丰富的集合框架&#xff0c;以及包含在Java标准库中的集合类。这些集合类提供了各种功能和操作&#xff0c;可以方便地对一组对象进行管理和操作。 目录 一、集合…

VUE引入DataV报错记录

DataV官网&#xff08;不支持Vue3&#xff09;&#xff1a;Welcome | DataV 一、按照官网引入后报错 【1】 Failed to resolve entry for package "dataview/datav-vue3". The package may have incorrect main/module/exports specified in its package.json. 将…

在docker中配置 Linux ls 配色方案 与 shell 提示符

发行版中默认的配置一般非常合理&#xff0c;但是docker中往往忽略了这些简单的配置&#xff0c;备忘一下 1. ls 配色方案 vim &#xff5e;/.bashrc 在文件最末尾加入如下一行内容&#xff1a; export LS_COLORS"rs0:di01;34:ln01;36:mh00:pi40;33:so01;35:do01;35:bd40…

在游戏里开公司!基于ERNIE SDK的多智能体游戏应用

在虚拟世界有一座神奇的办公室&#xff0c;当你输入你的创业方向&#xff0c;办公室的智慧打工人们将团结合作&#xff0c;为你的项目勤劳奔走&#xff0c;并在过程中&#xff0c;把日报周报都写好&#xff0c;让你随时掌握项目进度和最终成果&#xff01;该项目基于ERNIE SDK开…

前端canvas项目实战——简历制作网站(二)——右侧属性栏(颜色)

目录 前言一、效果展示二、实现步骤1. 实现一个自定义的选色板2. 创建属性工厂&#xff0c;为每个对象定制属性3. 为canvas对象注册监听器&#xff0c;点击不同对象时更新属性列表 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们实现了左侧工具栏&#xff0c;通过…

操作系统(3)---操作系统引导

在安装操作系统后&#xff0c;磁盘的分布如下&#xff1a; C盘是这个磁盘的活动分区&#xff08;又称主分区&#xff09;&#xff0c;安装了操作系统 开机过程如下&#xff1a; 1.计算机的主存由RAM和ROM组成&#xff0c;RAM关机数据消失&#xff0c;而ROM&#xff08;Basic In…

swagger2 和 knife4j 整合

swagger整合knife4j 导入依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version></dependency>引入配置 我们自己写一个配置类也好,我这里写…

iframe框架使用

一、什么是iframe框架 通俗讲就是将一个页面嵌入另一个页面&#xff0c;可以是本地的html,jsp也可以是网址如baidu.com 二、怎么用&#xff1f; <iframe name"uploadPage" src"/uploadImg.html" width"100%" height"50" marginh…

Rollup:打包 TypeScript - React 组件库

调用浏览器摄像头拍照组件 1、前提1、安装依赖2、添加 rollup.config.js 配置3、修改 package.json3.1 添加打包命令3.2 添加组件入口3.3 添加组件声明入口3.4 浏览器支持 1、前提 1.1 通过 create-react-app take-photo --template 创建前端应用 1.2 添加组件 TakePhoto (拍照…

磺化-Cy5-谷氨酰胺,Sulfo Cyanine5 Glutamine,被广泛应用于生物医学研究中

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;磺化-Cy5-谷氨酰胺&#xff0c;Sulfo Cyanine5 Glutamine&#xff0c;Sulfo Cy5 Glutamine 一、基本信息 产品简介&#xff1a;Sulfo Cyanine5 Glutamine作为一种荧光标记物&#xff0c;被广泛应用于生物医学研究中…

Android开发修炼之路——(一)Android App开发基础-1

本文介绍基于Android系统的App开发常识&#xff0c;包括以下几个方面&#xff1a;App开发与其他软件开发有什么不一样&#xff0c;App工程是怎样的组织结构又是怎样配置的&#xff0c;App开发的前后端分离设计是如何运作实现的&#xff0c;App的活动页面是如何创建又是如何跳转…

【C++修炼秘籍】List深度剖析

【C修炼秘籍】STL-List ☀️心有所向&#xff0c;日复一日&#xff0c;必有精进 ☀️专栏《C修炼秘籍》 ☀️作者&#xff1a;早凉 ☀️如果有错误&#xff0c;烦请指正&#xff0c;如有疑问可私信联系&#xff1b; 目录 【C修炼秘籍】STL-List 文章目录 前言 一、list介绍…

three.js中Meshline库的使用

three.js中Meshline的使用 库的地址为什么要使用MeshLine,three.js内置的线不好用吗?MeshLine入门MeshLine的深入思考样条曲线一个问题 库的地址 https://github.com/spite/THREE.MeshLine?tabreadme-ov-file 为什么要使用MeshLine,three.js内置的线不好用吗? 确实不好用,…

python222网站实战(SpringBoot+SpringSecurity+MybatisPlus+thymeleaf+layui)-Tag标签管理实现

锋哥原创的SpringbootLayui python222网站实战&#xff1a; python222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火爆连载更新中... )_哔哩哔哩_bilibilipython222网站实战课程视频教程&#xff08;SpringBootPython爬虫实战&#xff09; ( 火…

2023年CSDN年底总结-独立开源创作者第一年

2023年最大的变化&#xff0c;就是出来创业&#xff0c;当独立开源创作者&#xff0c;这一年发起SolidUI开源项目&#xff0c;把知乎重新开始运营起来。CSDN粉丝破万&#xff0c;CSDN博客专家和AI领域创作者。 2023年年度关键词&#xff1a;创业 https://github.com/CloudOrc…