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

设计模式之访问器模式(Visitor)的C++实现

1、访问器模式的提出

在软件开发过程中,早已发布的软件版本,由于需求的变化,需要给某个类层次结构增加新的方法。如果在该基类和子类中都添加新的行为方法,将给代码原有的结构带来破坏,同时,也违反了修改封闭,扩展开放的原则。访问器模式可以实现不改变原有代码结构的前提下,基于双向分发机制(2次虚函数绑定实例对象),通过扩展的方法实现新的接口。

2、需求描述

有2个固定数量的元素AB,每个元素有不同方法。A、B元素的方法有可能还会更新。请设计一个功能代码,可以应对方法更新的代码。

3、功能实现

(1)UML图如下:

 (2)代码实现如下:

#include <iostream>class ConcreteElementA;
class ConcreteElementB;
class Visitor
{
public:virtual void visitorElementA(ConcreteElementA& element)=0; //第二次虚函数virtual void visitorElementB(ConcreteElementB& element)=0;
};class Element
{
public:virtual void accept(Visitor& visitor)=0;    //第一次虚函数virtual ~Element(){};
};class ConcreteElementA:public Element
{
public:void accept(Visitor &visitor) override{visitor.visitorElementA(*this);}
};class ConcreteElementB:public Element
{
public:void accept(Visitor &visitor) override{visitor.visitorElementB(*this);}
};// 上面是稳定的代码结构 // 下面是扩展应对方法改变的功能类 
class ConcreteVisitor1:public Visitor
{
public:void visitorElementA(ConcreteElementA &element) override{std::cout << "Visitor1 process visitorElementA "<< &element << std::endl;}void visitorElementB(ConcreteElementB &element) override{std::cout << "Visitor1 process visitorElementB " << &element << std::endl;}
};class ConcreteVisitor2:public Visitor
{
public:void visitorElementA(ConcreteElementA &element) override{std::cout << "Visitor2 process visitorElementA " << &element<< std::endl;}void visitorElementB(ConcreteElementB &element) override{std::cout << "Visitor2 process visitorElementB " << &element << std::endl;}
};class Client{
public:void doWork(){ConcreteVisitor1 visitor1;ConcreteElementA element1A;element1A.accept(visitor1);ConcreteElementB element1B;element1B.accept(visitor1);ConcreteVisitor2 visitor2;ConcreteElementA element2A;element2A.accept(visitor2);ConcreteElementB element2B;element2B.accept(visitor2);}
};int main()
{Client obj;obj.doWork();return 0;
}

程序运行的结果如下:

 上面的代码,ConcreteElementA和ConcreteElementB的方法更新,通过Visitor基类的扩展子类来实现。

通过上面的代码可以看出,使用访问器模式的应用场景必须满足下面的条件:
(1)Element的子类个数必须确定。
(2)Visitor的子类必须实现Element的所有子类方法。

相关文章:

设计模式之访问器模式(Visitor)的C++实现

1、访问器模式的提出 在软件开发过程中&#xff0c;早已发布的软件版本&#xff0c;由于需求的变化&#xff0c;需要给某个类层次结构增加新的方法。如果在该基类和子类中都添加新的行为方法&#xff0c;将给代码原有的结构带来破坏&#xff0c;同时&#xff0c;也违反了修改封…...

Python之OS模块

os模块负责程序与操作系统的交互&#xff0c;提供了访问操作系统底层的接口;即os模块提供了非常丰富的方法用来处理文件和目录。 使用的时候需要导入该模块:import os...

vue 使用canvas 详细教程

Vue.js 中使用 Canvas Vue.js 是一个流行的 JavaScript 框架&#xff0c;用于构建用户界面。它提供了一种简洁的方式来管理和渲染数据&#xff0c;同时也支持与其他库和工具的集成。要在 Vue.js 中使用 Canvas&#xff0c;您可以按照以下步骤进行操作&#xff1a; 在 Vue.js …...

Git 基本操作【本地仓库与远程仓库的推送、克隆和拉取】

文章目录 一、Git简介二、Git的下载安装三、Git常规命令四、新建本地仓库五、本地分支操作六、Git远程仓库七、远程仓库克隆、抓取和拉取八、总结九、学习交流 一、Git简介 Git是分布式版本控制系统&#xff08;Distributed Version Control System&#xff0c;简称 DVCS&…...

FPGA开发

https://www.enclustra.com.cn/?bd_vid11435475462206745180 https://www.monolithicpower.cn/design-tools/design-tools/llc-design-tool.html https://www.elecfans.com/article/88/143/2012/20120718280641_2.html...

js手撕代码

1、实现instanceof运算符 instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上&#xff0c;运算符左侧是实例对象&#xff0c;右侧是构造函数。 const isInstanceof function(left,right){let proto Object.getPrototypeOf(left);while(true…...

typecho反序列化

typecho反序列化 环境的搭建 漏洞复现前提 <?php class Typecho_Feed {const RSS1 RSS 1.0;const RSS2 RSS 2.0;const ATOM1 ATOM 1.0;const DATE_RFC822 r;const DATE_W3CDTF c;const EOL "\n";private $_type;private $_items;public function __const…...

php程序设计的基本原则

单一职责原则&#xff08;SRP&#xff09;&#xff1a;一个类应该只有一个原因引起变化&#xff0c;即一个类应该只负责一项职责。 class User {private $name;private $email;public function __construct($name, $email) {$this->name $name;$this->email $email;}p…...

python execute() 使用%s 拼接sql 避免sql注入攻击 好于.format

1 execute(参数一:sql 语句) # 锁定当前查询结果行 cursor.execute("SELECT high, low, vol FROM table_name WHERE symbol %s FOR UPDATE;"% (symbol,)) 2 .format() cursor.execute("SELECT high, low, vol FROM table_name WHERE symbol {} FOR UPDATE;…...

RPC项目解析(1)

分布式通信框架&#xff1a;让远程方法调用和调用进程内方法一样简单 RPC通信原理 rpc&#xff1a;远程过程调用&#xff08;远程能够调用其他模块的方法&#xff09; 在rpc中需要发送时候&#xff0c;对发送的信息进行序列化&#xff0c;在服务端对接收到的信息进行反序列化…...

点云从入门到精通技术详解100篇-基于 RGB 图像与点云融合的三维点云分割算法及成像系统

目录 前言 相机和激光雷达标定研究现状 点云分割算法研究现状...

JDK8新特性

Lembda表达式 lembda表达式是一个简洁、可传递的匿名函数,实现了把代码块赋值给一个变量的功能 是我认为jdk1.8中最让人眼前一亮的特性&#xff08;我没用过其他函数式的语言&#xff09; 在了解表达式之前&#xff0c;我们先看两个概念 函数式接口 含有且仅含有一个抽象方法&…...

X86_64函数调用汇编程序分(2)

X86_64函数调用汇编程序分&#xff08;2&#xff09; 1 X86_64寄存器使用标准2 leaveq和retq指令2.1 leaveq2.2 retq 3 执行leaveq和retq之后栈的结构3.1 执行leaveq之后栈的结构3.1.1 test_fun_b函数执行leaveq之前的栈结构示意图3.1.2 test_fun_b函数执行leaveq之后的栈结构示…...

组件传值之ref(解决父传子动态绑定问题)

在父组件往子组件传值&#xff0c;子组件中要显示父组件的信息&#xff0c;首先是在网上搜的watch 来监听组组件的props,但是父组件只传一次&#xff0c;后续再更改就没了&#xff0c;所以我用的$refs props:{params:{type:Object;defult():{return {} } } }watch:{params: {/…...

vscode-server

1know_host清除 2 删除服务器里的home/user/.vscode-server&#xff08;不是根root下的vscode-server&#xff09;&#xff0c;删除时用户名保持一致。 3 ssh配置文件 /etc/ssh/sshd_config[想改变,使用root&#xff0c;修改文件权限] 4 删除修改后&#xff0c;重启Windows下…...

ubuntu 20.04安装开发环境总结_安装python

Ubuntu 20.04 是一款主要面向开发人员的操作系统之一&#xff0c;与此同时&#xff0c;它还支持多种开发环境和工具的使用。但是因为对市面上各种软件的支持没有window那样友好&#xff0c;所以对ubuntu系统安装配置各种环境的问题做了个总结 安装 PyCharm&#xff1a; 可以从…...

尚硅谷_宋红康_IntelliJ IDEA 常用快捷键一览表

1-IDEA的日常快捷键 第1组&#xff1a;通用型 说明快捷键复制代码-copyctrl c粘贴-pastectrl v剪切-cutctrl x撤销-undoctrl z反撤销-redoctrl shift z保存-save allctrl s全选-select allctrl a 第2组&#xff1a;提高编写速度&#xff08;上&#xff09; 说明快捷…...

Java设计模式之建造者模式详解(Builder Pattern)

在日常的开发工作中&#xff0c;我们常常需要创建一些复杂的对象。这些对象可能包含许多不同的属性&#xff0c;并且这些属性的初始化过程可能相当复杂。在这种情况下&#xff0c;建造者模式是一种非常有用的设计模式&#xff0c;因为它允许我们分步骤地创建复杂的对象。 概念和…...

TCP的滑动窗口与拥塞控制

客户端每发送的一个包&#xff0c;服务器端都应该有个回复&#xff0c;如果服务器端超过一定的时间没有回复&#xff0c;客户端就会重新发送这个包&#xff0c;直到有回复。 为了保证顺序性&#xff0c;每一个包都有一个 ID。在建立连接的时候&#xff0c;会商定起始的 ID 是什…...

MySQL更新语句执行过程

执行流程 update t set name XXX where id 1; 加载id1的记录所在的整页数据到缓存池&#xff1b;旧值写入undolog便于回滚&#xff1b;更新内存数据&#xff1b;写redo log到RedoBuff&#xff1b;redo log顺序写入磁盘&#xff0c;准备提交事务&#xff08;prepare阶段&…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP

编辑-虚拟网络编辑器-更改设置 选择桥接模式&#xff0c;然后找到相应的网卡&#xff08;可以查看自己本机的网络连接&#xff09; windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置&#xff0c;选择刚才配置的桥接模式 静态ip设置&#xff1a; 我用的ubuntu24桌…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...