当前位置: 首页 > news >正文

16 C++设计模式之职责链(Chain of Responsibility)模式

文章目录

      • 职责链(Chain of Responsibility)模式定义
      • 职责链(Chain of Responsibility)模式优缺点
        • 优点
        • 缺点
      • 职责链(Chain of Responsibility)模式构成与实现
        • 构成
        • 实例

职责链(Chain of Responsibility)模式定义

职责链模式(Chain of Responsibility),使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

职责链(Chain of Responsibility)模式优缺点

优点

  • 你可以控制请求处理的顺序。
  • 单一职责原则。你可对发起操作和执行操作的类进行解耦。
  • 开闭原则。你可以在不更改现有代码的情况下在程序中新增 处理者

缺点

  • 部分请求可能未被处理

职责链(Chain of Responsibility)模式构成与实现

构成

  • 处理者(Handler)声明了所有具体处理者的通用接口。该接口通常仅包含单个方法用于请求处理,但有时其还会包含一个设置链上下个处理者的方法。
  • 基础处理者(Base Handler)是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。通常情况下,该类中定义了一个保存对于下个处理者引用的成员变量。客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。该类还可以实现默认的处理行为:确定下个处理者存在后再将请求传递给它。
  • 具体处理者(Concrete Handlers)包含处理请求的实际代码。每个处理者接收到请求后,都必须决定是否进行处理,以及是否沿着链传递请求。处理者通常是独立且不可变的,需要通过构造函数一次性地获得所有必要地数据。
  • 客户端(Client)可根据程序逻辑一次性或者动态地生成链。值得注意的是,请求可发送给链上的任意一个处理者,而非必须是第一个处理者。

实例

Handler.h:

#ifndef HANDLER_H_
#define HANDLER_H_

// 抽象处理者, 在C++中是抽象基类
class ApproverInterface {
 public:
    // 添加上级
    virtual void setSuperior(ApproverInterface* superior) = 0;
    // 处理票据申请, 参数是票据面额
    virtual void handleRequest(double amount) = 0;
};

#endif  // HANDLER_H_

BaseHandler.h:

#ifndef BASE_HANDLER_H_
#define BASE_HANDLER_H_

#include <string>
#include "Handler.h"

class BaseApprover : public ApproverInterface {
 public:
    BaseApprover(double mpa, std::string n) : max_processible_amount_(mpa), name_(n), superior_(nullptr) {}
    // 设置上级
    void setSuperior(ApproverInterface* superior) {
        superior_ = superior;
    }
    // 处理票据
    void handleRequest(double amount) {
        // 可处理时直接处理即可
        if (amount <= max_processible_amount_) {
            printf("%s处理了该票据, 票据面额:%f\n", name_.c_str(), amount);
            return;
        }
        // 无法处理时移交给上级
        if (superior_ != nullptr) {
            printf("%s无权处理, 转交上级...\n", name_.c_str());
            superior_->handleRequest(amount);
            return;
        }
        // 最上级依然无法处理时报错
        printf("无人有权限处理该票据, 票据金额:%lf\n", amount);
    }

 private:
    double max_processible_amount_;  // 可处理的最大面额
    std::string name_;
    ApproverInterface* superior_;
};

#endif  // BASE_HANDLER_H_

ConcreteHandler.h:

#ifndef CONCRETE_HANDLER_H_
#define CONCRETE_HANDLER_H_

#include <string>
#include <cstdio>
#include "BaseHandler.h"

// 具体处理者: 组长(仅处理面额<=10的票据)
class GroupLeader : public BaseApprover {
 public:
    explicit GroupLeader(std::string name) : BaseApprover(10, name) {}
};

// 具体处理者: 经理(仅处理面额<=100的票据)
class Manager : public BaseApprover {
 public:
    explicit Manager(std::string name) : BaseApprover(100, name) {}
};


// 具体处理者: 老板(仅处理面额<=1000的票据)
class Boss : public BaseApprover {
 public:
    explicit Boss(std::string name) : BaseApprover(1000, name) {}
};

#endif  // CONCRETE_HANDLER_H_

main.cpp

#include "ConcreteHandler.h"

int main() {
    system("chcp 65001");
    // 请求处理者: 组长、经理和老板
    GroupLeader* group_leader = new GroupLeader("张组长");
    Manager* manager = new Manager("王经理");
    Boss* boss = new Boss("李老板");

    // 设置上级
    group_leader->setSuperior(manager);
    manager->setSuperior(boss);

    // 不同面额的票据统一先交给组长审批
    group_leader->handleRequest(8);
    group_leader->handleRequest(88);
    group_leader->handleRequest(888);
    group_leader->handleRequest(8888);

    delete group_leader;
    delete manager;
    delete boss;
    system("pause");
    return 0;
}

输出:

Active code page: 65001
张组长处理了该票据, 票据面额:8.000000
张组长无权处理, 转交上级...
王经理处理了该票据, 票据面额:88.000000
张组长无权处理, 转交上级...
王经理无权处理, 转交上级...
李老板处理了该票据, 票据面额:888.000000
张组长无权处理, 转交上级...
王经理无权处理, 转交上级...
无人有权限处理该票据, 票据金额:0.000000
Press any key to continue . . .

相关文章:

  • Kubernetes inotify watch 耗尽
  • LeetCode刷题(12)
  • linux系统命令-查看内存使用情况
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • 【艾思科技aisisoft.com.cn】物联网智能水族箱系统平台
  • 前后端数据接口协作提效实践
  • 分布式链路追踪技术
  • 日志收集分析平台项目-2-项目原理
  • 模型效果测试
  • 【Prism系列】Region的用法
  • 51单片机
  • 工匠精神育种陈温福培育一粒好种子 国稻种芯百团计划行动
  • MybatisPlus基本查询
  • 《MySQL实战45讲》——学习笔记01 “MySQL基本架构、redo log两阶段提交、事务隔离“
  • 【Selenium】一键摸鱼 一键采集数据
  • ----------
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Apache的基本使用
  • canvas 高仿 Apple Watch 表盘
  • docker容器内的网络抓包
  • Java Agent 学习笔记
  • JavaScript HTML DOM
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Mac转Windows的拯救指南
  • MySQL-事务管理(基础)
  • MySQL数据库运维之数据恢复
  • react-native 安卓真机环境搭建
  • SQLServer之创建数据库快照
  • 阿里研究院入选中国企业智库系统影响力榜
  • 如何学习JavaEE,项目又该如何做?
  • 主流的CSS水平和垂直居中技术大全
  • Java性能优化之JVM GC(垃圾回收机制)
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #在 README.md 中生成项目目录结构
  • (c语言)strcpy函数用法
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (安卓)跳转应用市场APP详情页的方式
  • (差分)胡桃爱原石
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (论文阅读30/100)Convolutional Pose Machines
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • .net操作Excel出错解决
  • .Net中ListT 泛型转成DataTable、DataSet
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • :如何用SQL脚本保存存储过程返回的结果集
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体
  • [C#基础知识]专题十三:全面解析对象集合初始化器、匿名类型和隐式类型
  • [c]统计数字
  • [IE编程] 如何编程清除IE缓存
  • [JMS 3] ActiveMQ实现简单的helloworld
  • [LLM][FT]大模型Fine-Tuning相关技术0