【设计模式之访问者模式 -- C++】

访问者模式 – 操作对象,分离算法

访问者模式(Visitor Pattern)是一种将算法与对象结构分离的设计模式。这种模式主要用于操作一个由许多对象构成的复杂对象结构,它能够在不修改这些对象的类的前提下定义作用于这些对象的新操作。

组成
  1. 访问者(Visitor)接口:定义了对每一个元素(Element)类访问操作的接口。通常会有一个访问方法对应每种类型的元素。
  2. 具体访问者(Concrete Visitor)类:实现访问者接口,定义了对每一个元素的具体访问行为。
  3. 元素(Element)接口:定义了一个接受访问者的方法(accept),该方法通常有一个访问者作为参数。
  4. 具体元素(Concrete Element)类:实现元素接口,定义了接受访问者的具体操作,通常是让访问者访问自己的元素。
  5. 对象结构(Object Structure):一个元素的集合,它提供了一个接口,允许访问者遍历自己的元素。
工作原理
  1. 访问者模式通过将数据结构与数据操作分离,使得在不修改已有程序结构的情况下,可以向已有的对象结构中添加新的操作。
  2. 当需要对一个复杂的对象结构(如组合树)进行操作时,可以使用访问者模式来避免对每个节点类都添加操作。相反,可以创建访问者类来专门处理这些操作。
  3. 元素类通过接受一个访问者对象,将自身作为参数传递给访问者的访问方法,从而实现对元素的操作。
优点
  1. 易于添加新的操作,增强了系统的灵活性。
  2. 将相关的操作集中到一个访问者对象中,而不是分散在多个元素类中,有助于集中管理和维护。
缺点
  1. 增加新的元素类变得困难,因为每增加一个新的元素类,都需要在每个访问者类中增加相应的访问操作。
  2. 可能会破坏封装,因为访问者模式通常需要元素类暴露一些访问其内部状态的操作,这可能会违反其封装原则。
实现
  1. 访问者(Visitor)接口:定义了对每一个元素(Element)类访问操作的接口。通常会有一个访问方法对应每种类型的元素。
class Visitor {
public:
    virtual void visitConcreteElementA(ConcreteElementA* elementA) = 0;
    virtual void visitConcreteElementB(ConcreteElementB* elementB) = 0;
    virtual ~Visitor() = default;
};

  1. 具体访问者(Concrete Visitor)类:实现访问者接口,定义了对每一个元素的具体访问行为。
// 具体访问者1
class ConcreteVisitor1 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA* elementA) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementA" << std::endl;
        elementA->operationA();
    }
    void visitConcreteElementB(ConcreteElementB* elementB) override {
        std::cout << "ConcreteVisitor1 visiting ConcreteElementB" << std::endl;
        elementB->operationB();
    }
};

// 具体访问者2
class ConcreteVisitor2 : public Visitor {
public:
    void visitConcreteElementA(ConcreteElementA* elementA) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementA" << std::endl;
        elementA->operationA();
    }
    void visitConcreteElementB(ConcreteElementB* elementB) override {
        std::cout << "ConcreteVisitor2 visiting ConcreteElementB" << std::endl;
        elementB->operationB();
    }
};

  1. 元素(Element)接口:定义了一个接受访问者的方法(accept),该方法通常有一个访问者作为参数。
class Element {
public:
    virtual void accept(Visitor* visitor) = 0; // 接受访问者
    virtual ~Element() = default;
};
  1. 具体元素(Concrete Element)类:实现元素接口,定义了接受访问者的具体操作,通常是让访问者访问自己的元素。
// 具体元素A
class ConcreteElementA : public Element {
public:
    void accept(Visitor* visitor) override {
        visitor->visitConcreteElementA(this);
    }
    void operationA() {
        std::cout << "ConcreteElementA operationA" << std::endl;
    }
};

// 具体元素B
class ConcreteElementB : public Element {
public:
    void accept(Visitor* visitor) override {
        visitor->visitConcreteElementB(this);
    }
    void operationB() {
        std::cout << "ConcreteElementB operationB" << std::endl;
    }
};
  1. 对象结构(Object Structure):一个元素的集合,它提供了一个接口,允许访问者遍历自己的元素。
int main() {
    std::vector<std::unique_ptr<Element>> elements;
    elements.push_back(std::make_unique<ConcreteElementA>());
    elements.push_back(std::make_unique<ConcreteElementB>());

    ConcreteVisitor1 visitor1;
    ConcreteVisitor2 visitor2;

    for (auto& element : elements) {
        element->accept(&visitor1);
        element->accept(&visitor2);
    }

    return 0;
}
  1. 结果
ConcreteVisitor1 visiting ConcreteElementA
ConcreteElementA operationA
ConcreteVisitor2 visiting ConcreteElementA
ConcreteElementA operationA
ConcreteVisitor1 visiting ConcreteElementB
ConcreteElementB operationB
ConcreteVisitor2 visiting ConcreteElementB
ConcreteElementB operationB

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

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

相关文章

Tortoise 删除文件

1、右击需要删除的文件&#xff0c;选择Delete 2、提交

遗传算法求解时间窗车辆路径规划问题(附python代码)

摘要 本研究提出了一种基于遗传算法的车辆路径规划&#xff08;VRP&#xff09;问题求解框架&#xff0c;它能够有效地处理一系列复杂约束&#xff0c;包括软时间窗、硬时间窗、行驶距离限制、车辆最大载重量、多个配送中心的协调、特定的配送顺序&#xff0c;以及多种车型的选…

【Python系列】探索 NumPy 中的 mean 函数:计算平均值的利器

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【AI技术】GPT-4o背后的语音技术猜想

前言&#xff1a; 本篇文章全文credit 给到 台大的李宏毅老师&#xff0c;李宏毅老师在机器学习上风趣幽默、深入浅出的讲解&#xff0c;是全宇宙学AI、讲中文学生的福音&#xff0c;强力推荐李宏毅老师的机器学习课程和深度学习 人工智能导论&#xff1b; 李宏毅老师的个人长…

LabVIEW机器视觉在质量控制中的应用

基于LabVIEW的机器视觉系统在质量控制中应用广泛&#xff0c;通过图像采集、处理和分析&#xff0c;自动检测产品缺陷、测量尺寸和识别标记&#xff0c;提高生产效率和产品质量。下面介绍LabVIEW机器视觉系统在质量控制中的实现方法、应用场景及其优势。 项目背景 在现代制造业…

Redis 入门篇

文章目录 Redis简介关系型数据库:非关系型数据库 Redis应用场景Redis下载和安装Redis 数据类型Redis 常用命令字符串 string 操作命令哈希 hash 操作命令列表 list 操作命令集合 set 操作命令有序集合 sorted set 操作命令通用命令 Jedis 快速入门配置依赖建立连接 / 操作 Jedi…

ShareX,屏幕截图、屏幕录制和文件共享,还提供了丰富的高级功能和自定义选项

ShareX是一个免费开源的Windows应用程序&#xff0c;用于屏幕截图、屏幕录制和文件共享。它不仅支持基本的屏幕截图功能&#xff0c;还提供了丰富的高级功能和自定义选项&#xff0c;使其成为提高工作效率和截图体验的利器。以下是ShareX v16.1.0便携版的主要功能和特色&#x…

NeRF从入门到放弃4: NeuRAD-针对自动驾驶场景的优化

NeuRAD: Neural Rendering for Autonomous Driving 非常值得学习的一篇文章&#xff0c;几乎把自动驾驶场景下所有的优化都加上了&#xff0c;并且也开源了。 和Unisim做了对比&#xff0c;指出Unisim使用lidar指导采样的问题是lidar的垂直FOV有限&#xff0c;高处的东西打不…

Vue: Module “vue“ has no exported member xxx

这个问题让我困扰了好一会儿&#xff0c;我询问了 chatgpt 和各种网站社区&#xff0c;尝试了切换依赖的版本&#xff0c;清除缓存等等&#xff0c;依然没有解决 不过算是有心栽花花不开&#xff0c;无心插柳柳成荫&#xff0c;碰巧解决了&#xff0c;也不知道是不是这个原因&a…

java收徒 java辅导 java试用期辅导 java零基础学习

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末报名辅导&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还有大家…

WinMerge v2 (开源的文件比较/合并工具)

前言 WinMerge 是一款运行于Windows系统下的免费开源的文件比较/合并工具&#xff0c;使用它可以非常方便地比较多个文档内容甚至是文件夹与文件夹之间的文件差异。适合程序员或者经常需要撰写文稿的朋友使用。 一、下载地址 下载链接&#xff1a;http://dygod/source 点击搜…

微信小程序-伪类选择器

一.伪类选择器 结构伪类常见书写方式&#xff1a; 第一类&#xff1a;找第几个孩子 1. :first-child 找第一个孩子2. :last-child 找最后一个孩子3. :nth-child()&#xff0c;正着找数字&#xff1a;写数字几就是找第几个孩子&#xff0c;2n或者even:找偶数2n1或者o…

python数据分析案例-信用卡违约预测分析

一、研究背景和意义 信用卡已经成为现代社会中人们日常生活中不可或缺的支付工具&#xff0c;它不仅为消费者提供了便利&#xff0c;还为商家提供了更广泛的销售渠道。然而&#xff0c;随着信用卡的普及和使用量的增加&#xff0c;信用卡违约问题逐渐成为金融机构面临的重要挑…

Java基础的重点知识-03-方法与数组

文章目录 方法数组 方法 定义方法的格式详解 修饰符 返回值类型 方法名(参数列表){//代码省略...return 结果; }修饰符&#xff1a; public static 固定写法返回值类型&#xff1a; 表示方法运行的结果的数据类型&#xff0c;方法执行后将结果返回到调用者参数列表&#xff1…

Pytho字符串的定义与操作

一、字符串的定义 Python 字符串是字符的序列&#xff0c;用于存储文本数据。字符串可以包括字母、数字、符号和空格。在 Python 中&#xff0c;字符串是不可变的&#xff0c;这意味着一旦创建了一个字符串&#xff0c;就不能更改其中的字符。但是&#xff0c;你可以创建新的字…

一文读懂LLM API应用开发基础(万字长文)

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;上一篇文章中我们详细介绍了LLM开发的基本概念&#xff0c;包括LLM的模型、特点能力以及应用&#xff1b;&#x1f632; 在本文中作者将通过&#xff1a…

Flutter ListView详解

文章示例代码 ListView常用构造 ListView 我们可以直接使用ListView 它的实现也是直接返回最简单的列表结构&#xff0c;粗糙没有修饰。 ListView 默认构建 效果 ///默认构建 Widget listViewDefault(List list) { List _list new List(); for (int i 0; i < list.le…

Java学习 - 网络IP协议簇 讲解

IP协议 IP协议全称 Internet Protocol互联网互连协议 IP协议作用 实现数据在网络节点上互相传输 IP协议特点 不面向连接不保证可靠 IP协议数据报结构 组成说明版本目前有IPv4和IPv6两种版本首部长度单位4字节&#xff0c;所以首部长度最大为 15 * 4 60字节区分服务不同…

视觉新纪元:解码LED显示屏的视角、可视角、最佳视角的最终奥秘

在璀璨夺目的LED显示屏世界里&#xff0c;每一个绚烂画面的背后&#xff0c;都离不开三个关键概念&#xff1a;视角、可视角与最佳视角。这些术语不仅是衡量显示效果的重要标尺&#xff0c;也是连接观众与精彩内容的桥梁。让我们一起走进这场视觉盛宴&#xff0c;探索那些让LED…

做Android开发怎么才能不被淘汰?

多学一项技能&#xff0c;可能就会成为你升职加薪的利器。经常混迹于各复杂业务线的人&#xff0c;才能跳出重复工作、不断踩坑的怪圈。而一个成熟的码农在于技术过关后&#xff0c;更突出其他技能对专业技术的附加值。 毋须讳言的是&#xff0c;35岁以后你的一线coding能力一…