C++设计模式——访问者模式

C++ 设计模式23:访问者模式 访问者模式(Visitor Pattern)是一种行为型设计模式,它主要用于将数据结构与数据操作分离。访问者模式允许在不修改现有数据结构的情况下,向对象结构中添加新的操作。这种模式主要包括访问者(Visitor)和被访问元素(Element)两个主要组成部分。访问者模式的主要优点是增加新的操作变得容易,因为不需要改变对象结构。同时,它也有一些缺点,如访问者模式使得对象结构变得不易修改,而且可能会破坏封装。 阅读详情

访问者模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。该模式的目的是要把处理从数据结构分离出来。访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。现在再来说说我之前经历过的那个项目。

是基于Windows Shell开发的一个项目,在一个容器中存储了很多的Shell Items,同时定义了对Items的操作,由于项目一直都在进行后期扩展,对Items的操作在后期都需要进行扩展的;而现在的做法是,定义一个操作类,该操作类中定义了一个集合,该集合存放Items,在该操作类中扩展对应的操作方法。现在想想如果使用访问者模式也是可以的,由于Items集合是固定的,当需要扩展集合的操作时,只需要添加对应的访问者即可。

 

UML类图

Visitor(访问者):为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
ConcreteVisitor(具体访问者):实现每个由Visitor声明的操作。每个操作实现本算法的一部分,而该算法片段乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
Element(元素):定义一个Accept操作,它以一个访问者为参数。
ConcreteElement(具体元素):实现Accept操作,该操作以一个访问者为参数。
ObjectStructure(对象结构):能够枚举它的元素,同时提供一个高层的接口以允许该访问者访问它的元素。

 

使用场合

  1. 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作;
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中;
  3. 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作;
  4. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

 

代码实现

#include <iostream>
#include <vector>
using namespace std;

class ConcreteElementA;
class ConcreteElementB;

class Visitor
{
public:
     virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
     virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};

class ConcreteVisitor1 : public Visitor
{
public:
     void VisitConcreteElementA(ConcreteElementA *pElementA);
     void VisitConcreteElementB(ConcreteElementB *pElementB);
};

void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
{
     // 现在根据传进来的pElementA,可以对ConcreteElementA中的element进行操作
}

void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{
     // 现在根据传进来的pElementB,可以对ConcreteElementB中的element进行操作
}

class ConcreteVisitor2 : public Visitor
{
public:
     void VisitConcreteElementA(ConcreteElementA *pElementA);
     void VisitConcreteElementB(ConcreteElementB *pElementB);
};

void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
{
     // ...
}

void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
{
     // ...
}

// Element object
class Element
{
public:
     virtual void Accept(Visitor *pVisitor) = 0;
};

class ConcreteElementA : public Element
{
public:
     void Accept(Visitor *pVisitor);
};

void ConcreteElementA::Accept(Visitor *pVisitor)
{
     pVisitor->VisitConcreteElementA(this);
}

class ConcreteElementB : public Element
{
public:
     void Accept(Visitor *pVisitor);
};

void ConcreteElementB::Accept(Visitor *pVisitor)
{
     pVisitor->VisitConcreteElementB(this);
}

// ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
class ObjectStructure
{
public:
     void Attach(Element *pElement);
     void Detach(Element *pElement);
     void Accept(Visitor *pVisitor);

private:
     vector<Element *> elements;
};

void ObjectStructure::Attach(Element *pElement)
{
     elements.push_back(pElement);
}

void ObjectStructure::Detach(Element *pElement)
{
     vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
     if (it != elements.end())
     {
          elements.erase(it);
     }
}

void ObjectStructure::Accept(Visitor *pVisitor)
{
     // 为每一个element设置visitor,进行对应的操作
     for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
     {
          (*it)->Accept(pVisitor);
     }
}

int main()
{
     ObjectStructure *pObject = new ObjectStructure;

     ConcreteElementA *pElementA = new ConcreteElementA;
     ConcreteElementB *pElementB = new ConcreteElementB;

     pObject->Attach(pElementA);
     pObject->Attach(pElementB);

     ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
     ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;

     pObject->Accept(pVisitor1);
     pObject->Accept(pVisitor2);

     if (pVisitor2) delete pVisitor2;
     if (pVisitor1) delete pVisitor1;
     if (pElementB) delete pElementB;
     if (pElementA) delete pElementA;
     if (pObject) delete pObject;

     return 0;
}

总结

访问者模式的基本思想如下:首先拥有一个由许多对象构成的对象结构,就是上面代码中的ObjectStructure,这些对象的类都拥有一个Accept方法用来接受访问者对象;访问者是一个接口,它拥有一个Visit方法,这个方法对访问到的对象结构中不同类型的元素做出不同的操作;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施Accept方法,在每一个元素的Accept方法中回调访问者的Visit方法,从而使访问者得以处理对象结构的每一个元素。我们就可以针对对象结构设计不同的访问者类来完成不同的操作。

设计模式中经常说的一句话是:发现变化并封装之。是否采用访问者模式,就要看“变化”是什么。访问者模式中,“变化”是具体访问者,其次是对象结构;但是,如果具体元素也会发生改变,就万万不能使用访问者模式,因为这样“牵一发而动全身”,后期的维护性就太差了。

C++中的访问者模式(Visitor Pattern)是一种常见的设计模式,它可以帮助我们在不改变对象结构的情况下,定义新的操作。本文将详细介绍访问者模式的实现... 在这个例子中,我们定义了Animal类和其不同的子类,然后在Visitor类中定义了访问方法。比如,Feeder类的visit()方法用于给动物喂食,Doctor类的visit()方法用于给动物看病。C++中的访问者模式(Visitor Pattern)是一种常见的设计模式,它可以帮助我们在不改变对象结构的情况下,定义新的操作。总之,访问者模式是一种常见的设计模式,它可以帮助我们简化复杂数据结构的操作,并且不会改变数据结构本身。通过本文的介绍,相信大家已经掌握了访问者模式的实现原理和代码实现方法。 阅读详情

相关推荐

H3C设备VRF配置实战:5步搞定多业务网络隔离(附排错技巧)

本文详细介绍了在H3C设备上配置VRF(虚拟路由转发)实现多业务网络隔离的实战方法。通过五步配置流程,从创建VPN-instance、绑定接口到配置独立路由表,帮助网络工程师在单台设备上构建逻辑隔离的企业级网络,并分享了高级路由配置与常见排错技巧。

gold8的专栏 936

C++ 设计模式-访问者模式

C++ 设计模式-访问者模式 参考网址:https://www.cnblogs.com/suzhou/p/designpattern17visitor.html 意图 表示一个作用于某对象结构的各元素的操作。它使你可以再不改变各元素的类的前提下定义作用于这些元素的新操作 适用性 在下列情况下使用Visitor模式: 一个对象结构包含很多类对象 需要对其中的对象进行很多不同的并且不相关的操作 对象很...

wangdamingll的博客 1264

BLDC六步换相驱动实战:从霍尔真值表到PWM调速的代码实现

本文详细解析了BLDC六步换相驱动原理,从霍尔真值表解读到PWM调速的代码实现,提供了基于STM32的实战方案。重点介绍了霍尔信号解码、换相状态机设计以及PWM动态调速策略,帮助开发者快速掌握无刷电机驱动技术。

weixin_28273593的博客 210

C++ 设计模式——访问者模式

访问者模式(Visitor Pattern)是一种行为设计模式,其目的是将数据结构与数据操作分离,使得在不修改已有程序代码的情况下,可以添加新的操作。这种模式通过定义一个访问者类,来改变一个元素类的执行算法。访问者模式使得你能够在不改变元素类的前提下,定义作用于这些元素的新操作。

慢慢记录,慢慢更新。 2512

iPhone免越狱Git服务器搭建教程-iSH

iPhone免越狱Git服务器搭建教程

jts666的博客 4426

ESP32驱动TFT屏幕实战:LVGL与TFT_eSPI完美结合

本文详细介绍了如何在ESP32上结合TFT_eSPI驱动库与LVGL图形库,实现高效、流畅的嵌入式GUI开发。内容涵盖硬件连接、软件环境搭建、库配置、LVGL移植、界面创建及性能优化等全流程实战指南,帮助开发者快速构建低成本、高性能的交互式显示应用。

weixin_29206669的博客 200

访问者模式【行为模式C++】

访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。访问者模式主要解决的是数据与算法的耦合问题,尤其是在数据结构比较稳定,而算法多变的情况下。为了不污染数据本身,访问者会将多种算法独立归档,并在访问数据时根据数据类型自动切换到对应的算法,实现数据的自动响应机制,并确保算法的自由扩展。访问者模式在实际开发中使用的非常少,因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差,可维护性变差,在没有特别必要的情况下,不建议使用访问者模式。

weixin_39775340的博客 2020

【教程4>第2章>第18节】 GMSK调制系统的FPGA开发与matlab对比验证

GMSK(高斯最小频移键控)是一种连续相位的频移键控(CPFSK)调制方法,它在数字通信中得到了广泛应用,特别是在移动通信系统中。GMSK通过限制频率偏差的累积来减少带外辐射,并通过使用高斯滤波器对。

FPGA/MATLAB学习教程/源码/项目合作开发 998

C++设计模式之访问者模式

访问者模式(Visitor Pattern)是⼀种行为型设计模式,可以在不改变对象结构的前提下,对对象中的元素进行新的操作。

K1_uestc的博客 1786

YOLOv8改进:注意力系列篇 |高效的通道先验卷积注意力(CPCA) | 中科院 2023.6

高效的通道先验卷积注意力(CPCA)方法,支持注意力权重在通道和空间维度上的动态分布;

会AI的学姐 2041

mapbox进阶,dem数据转为等高面,加载转换后的等高面到地图

本文详细介绍如何基于mapbox-gl v3.*.* 版本,使用dem数据转为等高面,加载转换后的等高面到地图,亲测可用。希望能帮助到您。一起学习,加油!加油!

我哎GIS博客 406

C++设计模式(19)——访问者模式

C++ 访问者模式

伍粟的博客 1360

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

【c++设计模式25】行为模式10:访问者模式(Visitor Pattern)

访问者模式定义了两个关键角色:访问者(Visitor)和元素(Element)。访问者定义了针对不同元素的操作方法,而元素则是被访问者访问的对象。通过访问者的多态调用,可以实现对元素进行不同的操作。

junxuezheng的博客 1158

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++设计模式——访问者模式(visitor pattern)

一、原理讲解 1.1意图 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 1.2应用场景 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作; 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免这些操作“污染”这些对象的类; 定义对象结构的类很少改变,但经常需要在此结构定义新的操作; 1.3结构图(UML图) 1.4代码实现步骤 a1 定义接口命令类Command,定义一个执行接口函数e

净无邪博客 1771

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

C++ 设计模式 - 访问者模式

访问者模式将作用于对象层次结构的操作封装为一个对象,并使其能够在不修改对象层次结构的情况下定义新的操作。《设计模式:可复用面向对象软件的基础》一书中的访问者模式因两个原因而具有传奇色彩:一是因为它的复杂性,二是因为它使用了一种名为“双重分派”的技术。双重分派指的是根据对象和函数参数选择成员函数的过程。当然,访问者模式的复杂性主要在于 C++ 本身不支持双重分派。在讨论单分派和双重分派之前,让我先谈谈访问者模式。什么是“双重分派”?

GPU全栈博主 1171

C++ 设计模式:访问者模式(Visitor Pattern)

C++ 设计模式:访问者模式(Visitor Pattern)

冀晓武的博客 729

C++设计模式行为模式———访问者模式

在访问者模式中,数据结构(元素)与针对数据结构的操作/处理(访问者)被分隔开了,通过访问者子类来访问数据结构中的元素,对这些元素的处理交给访问者子类。当需要增加新的处理时,只需要编写新的访问者子类并让数据结构接受(Accept)访问者的访问即可,如果不进行这样的分隔,那么这些操作就得放人元素所属的类中。图):提供一个作用于某对象结构中的各元素的操作表示,便可以在不改变各元素类的前提下定义(扩展)作用于这些元素的新操作。也就是说,允许一个或者多个操作应用到一组对象上,使对象本身和操作解耦。

无敌岩雀的博客 1350

C++ 设计模式之访问者模式

C++ 设计模式之访问者模式

L_qingting的博客 619

大话设计模式访问者模式c++实现

访问者模式 其他二十三种设计模式 #include<iostream> #include<list> using namespace std; //访问者模式 class Action; //抽象对象类 class Person { public: virtual void Accept(Action* _visitor) = 0; }; class Man; class Woman; //抽象状态类 class Action { public: virtual void

wode_0828的博客 171

设计模式-访问者模式-C++

访问者模式:作用于一个对象各个元素的操作,可以在不改变对象结构的情况下,增加这个元素的新操作 应用场景:一个对象的数据结构比较稳定,但是对这个对象的各个元素的操作可以任意扩展。 例子:我们去银行柜台办业务,一般情况下会开几个柜台,你去其中任何一个柜台办理都是可以的。我们的访问者模式定义为:对于银行柜台来说,他们是不用变化的(被访问的对象),就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们...

wb175208的专栏 393

基于C++的《Head First设计模式》笔记——访问者模式

本文介绍了访问者设计模式的实现原理与应用场景。作者通过电脑硬件检测的案例,对比了传统继承多态写法与访问者模式的差异。传统写法将检测逻辑耦合在硬件类中,违反开闭原则;而访问者模式将数据与操作分离,硬件类只负责存储数据,检测逻辑集中在访问者类中。该模式通过双分派机制实现动态绑定,新增功能只需添加访问者而无需修改原有代码,完美符合开闭原则。文章详细分析了访问者模式的优缺点,指出其适合元素类型稳定但需要频繁添加功能的场景,如硬件检测系统。最后强调设计模式的价值在于提高代码的可扩展性和可维护性。

Yu_Lijing的博客 511

我所理解的设计模式(C++实现)——访问者模式(Visitor Pattern)

我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。我们的访问者模式可以很好付诸在这个场景中:对于银行柜台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们作为访问者,今天来银行可能是取消费流水,明天来银行可能是去办理手机银行业务,这些是我们访问者的操作,一直是在变化的。

十八道胡同的博客专栏 2万+

Linux C++ 066-设计模式之访问者模式

本节关键字:Linux、C++、设计模式、访问者模式 相关库函数:

Tianwx的博客 554
上一篇: C++设计模式——策略模式
下一篇: C++设计模式——模板方法模式
CoderAldrich
博客等级 码龄12年 431粉丝 24原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值