23种设计模式之C++实践(三)

23种设计模式之C++实践

  • 3. 设计模式
    • (三)行为型模式
      • 14. 职责链模式——请求的链式处理
        • 职责链模式总结
      • 15. 命令模式:请求发送者与接收者解耦
        • 命令模式总结
      • 16. 解释器模式——自定义语言的实现
        • 解释器模式总结
      • 17. 迭代器模式——遍历聚合对象中的元素
        • 迭代器模式总结
      • 18. 中介者模式——协调多个对象之间的交互
        • 中介者模式总结
      • 19. 备忘录模式——撤销功能的实现
        • 备忘录模式总结
      • 20. 观察者模式——对象间的联动
        • 观察者模式总结
      • 21. 状态模式——对象状态及其转换
        • 状态模式总结
      • 22. 策略模式——算法的封装和切换
        • 策略模式总结
      • 23. 模板方法模式——定义算法的框架
        • 模板方法模式总结
      • 24. 访问者模式——操作复杂对象结构
        • 访问者模式总结

3. 设计模式

(三)行为型模式

14. 职责链模式——请求的链式处理

  1. 职责链模式(Chain of Responsibility Pattern):避免将请求接收者与发送者耦合在一起,让多个对象都有机会接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,知道有对象处理它为止。

  2. 要点

    1. 职责链模式并不创建职责链,职责链的创建工作通常是由客户端完成。
  3. 结构图

  4. 适用场景示例

    采购单的分级审批:不同级别的人员可以审批不同金额的采购单。

  5. 代码示例

    // Approver.h
    /*** @brief 审批者接口**/
    class Approver {protected:Approver* successor;std::string name;public:Approver(std::string name) : name(name) {}void setSuccessor(Approver* successor) {this->successor = successor;return;}virtual void processRequest(PurchaseRequest*) = 0;
    };class Director : public Approver {public:Director(std::string name) : Approver(name) {}public:void processRequest(PurchaseRequest* request) override {if (request->getAmount() < 5000) {printf("主任:%s 审批采购单:%d,金额:%f元,采购目的:%s。\n",name.c_str(), request->getNumber(), request->getAmount(),request->getPurpose().c_str());printf("审批通过!\n");} else {printf("%s审批通过,", name.c_str());printf("进入下一层审批\n");this->successor->processRequest(request);}return;}
    };class VicePresident : public Approver {public:VicePresident(std::string name) : Approver(name) {}public:void processRequest(PurchaseRequest* request) override {if (request->getAmount() < 10000) {printf("副董事长:%s 审批采购单:%d,金额:%f元,采购目的:%s。\n",name.c_str(), request->getNumber(), request->getAmount(),request->getPurpose().c_str());printf("审批通过!\n");} else {printf("%s审批通过,", name.c_str());printf("进入下一层审批\n");this->successor->processRequest(request);}return;}
    };class President : public Approver {public:President(std::string name) : Approver(name) {}public:void processRequest(PurchaseRequest* request) override {if (request->getAmount() < 200000) {printf("董事长:%s 审批采购单:%d,金额:%f元,采购目的:%s。\n",name.c_str(), request->getNumber(), request->getAmount(),request->getPurpose().c_str());printf("审批通过!\n");} else {printf("%s审批通过,", name.c_str());printf("进入下一层审批\n");this->successor->processRequest(request);}return;}
    };class Congress : public Approver {public:Congress(std::string name) : Approver(name) {}public:void processRequest(PurchaseRequest* request) override {if (request->getAmount() < 1000000) {printf("董事会:审批采购单:%d,金额:%f元,采购目的:%s。\n",request->getNumber(), request->getAmount(),request->getPurpose().c_str());printf("审批通过!\n");} else {printf("董事会审批不通过!\n");}return;}
    };// PurchaseRequest.h
    class PurchaseRequest {private:double amount;int number;std::string purpose;public:PurchaseRequest(double amount, int number, std::string purpose): amount(amount), number(number), purpose(purpose) {}void setAmount(double amount) {this->amount = amount;return;}void setNumber(double number) {this->number = number;return;}void setPurpose(std::string purpose) {this->purpose = purpose;return;}double getAmount() { return this->amount; }int getNumber() { return this->number; }std::string getPurpose() { return this->purpose; }
    };
    
  6. 代码测试

    • 测试代码

      int main(int argc, char** argv) {printf("I'm Chain Of Responsibility Pattern!\n");// begin testApprover *num1, *num2, *num3, *num4;num1 = new Director("季");num2 = new VicePresident("叔");num3 = new President("仲");num4 = new Congress("伯");num1->setSuccessor(num2);num2->setSuccessor(num3);num3->setSuccessor(num4);PurchaseRequest* request = new PurchaseRequest(500, 10001, "差旅报销");num1->processRequest(request);PurchaseRequest* request2 = new PurchaseRequest(5000, 10002, "差旅报销");num1->processRequest(request2);PurchaseRequest* request3 = new PurchaseRequest(50000, 10003, "差旅报销");num1->processRequest(request3);PurchaseRequest* request4 = new PurchaseRequest(500000, 10004, "差旅报销");num1->processRequest(request4);PurchaseRequest* request5 = new PurchaseRequest(5000000, 10005, "差旅报销");num1->processRequest(request5);// end testreturn 0;
      }
    • 输出

      I’m Chain Of Responsibility Pattern!
      主任:季 审批采购单:10001,金额:500.000000元,采购目的:差旅报销。
      审批通过!
      季审批通过,进入下一层审批
      副董事长:叔 审批采购单:10002,金额:5000.000000元,采购目的:差旅报销。
      审批通过!
      季审批通过,进入下一层审批
      叔审批通过,进入下一层审批
      董事长:仲 审批采购单:10003,金额:50000.000000元,采购目的:差旅报销。
      审批通过!
      季审批通过,进入下一层审批
      叔审批通过,进入下一层审批
      仲审批通过,进入下一层审批
      董事会:审批采购单:10004,金额:500000.000000元,采购目的:差旅报销。
      审批通过!
      季审批通过,进入下一层审批
      叔审批通过,进入下一层审批
      仲审批通过,进入下一层审批
      董事会审批不通过!

职责链模式总结
  • 优点
    1. 使得一个对象无须知道其他哪一个对象处理其请求。
    2. 请求处理对象只需维持一个指向其后继者的引用,可简化对象的相互连接。
    3. 给对象分配职责时更灵活
    4. 在客户端增加一个新的具体请求处理者时无需修改原有代码,只需要在客户端重建链即可。
  • 缺点
    1. 请求可能因职责链没有被正确分配而得不到处理
    2. 职责链过长时,影响系统性能。
    3. 可能造成死循环
  • 适用场景
    1. 有多个对象处理同一个请求,具体哪个对象处理该请求待运行时再确定。
    2. 在不明确指定接收者的情况下,向多个对象种的一个提交一个请求。
    3. 可动态指定一组对象处理请求。

15. 命令模式:请求发送者与接收者解耦

  1. 命令模式(Command Pattern):将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

  2. 要点

    1. 引入抽象命令类,对请求进行封装,将发出命令的责任与执行命令的责任分割开。
  3. 结构图

  4. 适用场景示例

    自定义功能键

  5. 代码示例

    // Command.h
    /*** @brief 抽象命令类**/
    class Command {public:virtual void execute() = 0;
    };/*** @brief 帮助命令类:具体命令类**/
    class HelpCommand : public Command {private:HelpHandler* helpHandler;public:HelpCommand() { helpHandler = new HelpHandler(); }public:void execute() override {helpHandler->display();return;}
    };/*** @brief 最小化命令类:具体命令类**/
    class MinimizeCommand : public Command {private:WindowHandler* helpHandler;public:MinimizeCommand() { helpHandler = new WindowHandler(); }public:void execute() override {helpHandler->minimize();return;}
    };// FunctionButton.h
    /*** @brief 功能键类:请求发送者**/
    class FunctionButton {private:std::string name;Command* command;public:FunctionButton(std::string name) : name(name) {}std::string getName() { return name; }void setCommand(Command* command) {this->command = command;return;}void onClick() {printf("点击功能键\n");command->execute();return;}
    };class FBSettingWindow {private:std::string title;std::vector<FunctionButton*> functionButtons;public:FBSettingWindow(std::string title) { this->title = title; }public:void setTitle(std::string title) {this->title = title;return;}std::string getTitle() { return this->title; }void addFunctionButton(FunctionButton* fb) {functionButtons.push_back(fb);return;}void removeFunctionButton(FunctionButton* fb) {auto begin = functionButtons.begin();auto end = functionButtons.end();while (begin != end) {if (*begin == fb) {functionButtons.erase(begin);break;}begin++;}return;}void display() {printf("显示窗口:%s\n", this->title.c_str());printf("显示功能键:");for (auto fb : functionButtons) {printf("%s ", fb->getName().c_str());}printf("\n");return;}
    };// Handler.h
    /*** @brief 帮助文档处理类:请求接收者**/
    class HelpHandler {public:void display() {printf("显示帮助文档\n");return;}
    };/*** @brief 窗口处理类:请求接收者**/
    class WindowHandler {public:void minimize() {printf("将窗口最小化至托盘\n");return;}
    };
    
  6. 代码测试

    • 测试代码

      int main(int argc, char** argv) {printf("I'm Command Pattern!\n");// begin testFBSettingWindow* fbsw = new FBSettingWindow("功能键设置");FunctionButton *fb1, *fb2;fb1 = new FunctionButton("功能键1");fb2 = new FunctionButton("功能键2");Command *command1, *command2;command1 = new HelpCommand();command2 = new MinimizeCommand();fb1->setCommand(command1);fb2->setCommand(command2);fbsw->addFunctionButton(fb1);fbsw->addFunctionButton(fb2);fbsw->display();fb1->onClick();fb2->onClick();// end testreturn 0;
      }
    • 输出

      I’m Command Pattern!
      显示窗口:功能键设置
      显示功能键:功能键1 功能键2
      点击功能键
      显示帮助文档
      点击功能键
      将窗口最小化至托盘

命令模式总结
  • 优点
    1. 降低系统的耦合度。
    2. 增加新的命令很容易
    3. 可以比较容易地设计一个命令队列。
    4. 可使用命令队列实现”撤销请求“和”回复请求“。
  • 缺点
    1. 可能导致某些系统中有过多的具体命令类。
  • 适用场景
    1. 系统需要将请求调用者与请求接收者解耦。
    2. 系统需要在不同的时间指定请求、将请求排队和执行请求。
    3. 系统需要支持命令的撤销操作和恢复操作。

16. 解释器模式——自定义语言的实现

  1. 解释器模式(Interpreter Pattern

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM进程缓存

引言 缓存在日常开发中启动至关重要的作用&#xff0c;由于是存储在内存中&#xff0c;数据的读取速度是非常快的&#xff0c;能大量减少对数据库的访问&#xff0c;减少数据库的压力。我们把缓存分为两类&#xff1a; 分布式缓存&#xff0c;例如Redis&#xff1a; 优点&…

服务器GPU占用,kill -9 PID 用不了,解决办法

PID&#xff08;progress ID 进程ID&#xff09; 上图为占用情况&#xff0c;使用下面的指令都不管用 kill -9 PID kill -15 PID # 加入sudo 还是不行 # 等等网上的 chatgpt 提供的其他办法&#xff0c;一圈试了下来还是不管用最后解决办法 首先用下面的指令查看进程的树结构…

51单片机LED与无源蜂鸣器模块

IO口的使用1 本文主要对51单片机的LED灯的使用以及蜂鸣器的使用进行介绍&#xff0c;其中包括一些实例分析&#xff1a; 1.实现发光二极管的从左到右的流水点亮 2.左右来回循环的流水灯 3.蜂鸣器以一定频率响 文章目录 IO口的使用1一、LED灯举个栗子一举个栗子二 二、蜂鸣器2.1…

第一百九十九回 如何获取设备信息

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 我们在上一章回中介绍了包管理相关的内容&#xff0c;本章回中将介绍如何使用url_launcher包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里介绍url_launcher包主要用来打开…

Python开发运维:Python调用K8S API实现资源管理

目录 一、实验 1.Python操作K8S API获取资源 2.Python操作K8S API创建deployment资源 3.Python操作K8S API删除k8s资源 4.Python操作K8S API修改k8s资源 5.Python操作K8S API查看k8s资源 二、问题 1.Windows11安装kubernetes报错 2.Python通过调用哪些方法实现Pod和De…

【深度学习】注意力机制(一)

本文介绍一些注意力机制的实现&#xff0c;包括SE/ECA/GE/A2-Net/GC/CBAM。 目录 一、SE&#xff08;Squeeze-and-Excitation&#xff09; 二、ECA&#xff08;Efficient Channel Attention&#xff09; 三、GE&#xff08;Gather-Excite&#xff09; 四、A2-Net(Double A…

Python中的汉诺塔问题求解和科赫曲线绘制(递归扩展)

汉诺塔问题求解&#xff0c;在a杆上自上而下、由大到小顺序地串有64个盘子&#xff0c;要求把a杆上的盘子借助c杆全部移动到b杆上。 def hanoi(n,a,b,c):if(n>0):hanoi(n-1,a,c,b) #n-1个盘子&#xff0c;借助b杆放在c杆上print(“move disc no:{} from pile {} to {}”.f…

uniapp移动端悬浮按钮(吸附边缘)

Uniapp移动端悬浮按钮可以通过CSS实现吸附边缘的效果。具体实现步骤如下&#xff1a; html&#xff1a; <movable-area class"movable-area"><movable-view class"movable-view" :position"position" :x"x" :y"y"…

网络协议疑点记录

1.RIP, OSPF,BGP 首先什么是自治系统:治系统就是几个路由器组成了一个小团体 ?,小团体内部使用专用的协议进行通信,而小团体和小团体之间也使用专用的协议进行通信。 IGP RIP 距离矢量路由算法,bellman-ford算法,每个路由节点知道全局的路由信息,通过和邻居交换信息得…

【KCC@南京】KCC南京“数字经济-开源行”活动回顾录

11月26日&#xff0c;由KCC南京、中科南京软件研究所、傲空间、PowerData联合主办的 KCC南京“数字经济-开源行” 的活动已圆满结束。此次活动&#xff0c;3 场主题研讨&#xff0c;11 场分享&#xff0c;现场参会人数 60&#xff0c;线上直播观看 3000&#xff0c;各地小伙伴从…

this.$emit(‘update:isVisible‘, false)作用

这个写是不是很新颖&#xff0c;传父组件传值&#xff01;这是什么鬼。。。 假设你有以下逻辑业务。在A页面弹出一个组件B&#xff0c;A组件里面使用B组件&#xff0c;是否展示B组件你使用的是baselineShow变量控制&#xff01; <BaselineData :isVisible.sync"basel…

某音上很火的圣诞树分享

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 效果截图&#xff08;这里不给动态了&#xff0c;某音到处都是了&#xff09;&#xff1a; 源代码&#xff1a; <script src"…