新闻中心

C++如何实现一个访问者模式(Visitor Pattern)_C++设计模式与访问者实现

2025-11-11
浏览次数:
返回列表
访问者模式通过双重分发在不修改元素类的前提下扩展操作,由抽象元素、具体元素、抽象访问者、具体访问者和对象结构组成,适用于元素稳定但操作多变的场景,如AST处理,优点是符合开闭原则,缺点是新增元素需修改所有访问者。

c++如何实现一个访问者模式(visitor pattern)_c++设计模式与访问者实现

访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不修改对象结构的前提下,为对象结构中的元素添加新的操作。C++中实现访问者模式的关键在于双重分发(Double Dispatch),通过虚函数机制实现动态调用。

访问者模式的核心组成

访问者模式包含以下几个核心部分:

  • 抽象元素(Element):定义一个accept方法,接收访问者对象。
  • 具体元素(ConcreteElement):实现accept方法,调用访问者的visit方法。
  • 抽象访问者(Visitor):声明一组visit函数,对应不同的元素类型。
  • 具体访问者(ConcreteVisitor):实现具体的访问逻辑。
  • 对象结构(ObjectStructure):如容器,用于遍历并接受访问者。

代码实现示例

下面是一个简单的C++实现,模拟对不同形状进行“绘制”和“计算面积”的操作:

// 抽象访问者class ShapeVisitor;

// 抽象元素class Shape {public:virtual ~Shape() = default;virtual void accept(ShapeVisitor& visitor) = 0;};

// 具体元素:圆形class Circle : public Shape {public:double radius;Circle(double r) : radius(r) {}

<strong>void accept(ShapeVisitor& visitor) override {</strong>
    <strong>visitor.visit(*this);</strong>
<strong>}</strong>

};

// 具体元素:矩形class Rectangle : public Shape {public:double width, height;Rectangle(double w, double h) : width(w), height(h) {}

<strong>void accept(ShapeVisitor& visitor) override {</strong>
    <strong>visitor.visit(*this);</strong>
<strong>}</strong>

};

// 抽象访问者class ShapeVisitor {public:virtual ~ShapeVisitor() = default;virtual void visit(Circle& circle) = 0;virtual void visit(Rectangle& rectangle) = 0;};

// 具体访问者:绘图class DrawVisitor : public ShapeVisitor {public:void visit(Circle& circle) override {std::cout }

<strong>void visit(Rectangle& rectangle) override {</strong>
    <strong>std::cout << "绘制宽 " << rectangle.width << " 高 " << rectangle.height << " 的矩形\n";</strong>
<strong>}</strong>

};

// 具体访问者:计算面积class AreaVisitor : public ShapeVisitor {public:double totalArea = 0.0;

<strong>void visit(Circle& circle) override {</strong>
    <strong>double area = 3.14159 * circle.radius * circle.radius;</strong>
    <strong>std::cout << "圆形面积: " << area << "\n";</strong>
    <strong>totalArea += area;</strong>
<strong>}</strong>

<strong>void visit(Rectangle& rectangle) override {</strong>
    <strong>double area = rectangle.width * rectangle.height;</strong>
    <strong>std::cout << "矩形面积: " << area << "\n";</strong>
    <strong>totalArea += area;</strong>
<strong>}</strong>

};

// 使用示例int main() {std::vector<:unique_ptr>> shapes;shapes.push_back(std::make_unique(5.0));shapes.push_back(std::make_unique(4.0, 6.0));

<strong>DrawVisitor drawVisitor;</strong>
<strong>AreaVisitor areaVisitor;</strong>

<strong>for (auto& shape : shapes) {</strong>
    <strong>shape->accept(drawVisitor);</strong>
<strong>}</strong>

<strong>for (auto& shape : shapes) {</strong>
    <strong>shape->accept(areaVisitor);</strong>
<strong>}</strong>

<strong>std::cout << "总面积: " << areaVisitor.totalArea << "\n";</strong>
<strong>return 0;</strong>

}

使用场景与优缺点

访问者模式适合以下情况:

  • 需要对一个对象结构中的多种元素执行不同的操作,且希望将操作分离。
  • 元素类相对稳定,但操作经常扩展。
  • 避免在元素类中不断添加新方法导致职责膨胀。

优点:

  • 符合开闭原则:新增操作只需添加新的访问者。
  • 集中相关操作,便于维护。

缺点:

  • 增加新元素类型时,所有访问者都要修改。
  • 破坏封装性:访问者可能需要访问元素的内部数据。
  • 代码复杂度提高,理解成本上升。

基本上就这些。访问者模式在编译器、AST处理、UI控件遍历等场景中较为常见,合理使用能提升系统扩展性。

以上就是C++如何实现一个访问者模式(Visitor Pattern)_C++设计模式与访问者实现的详细内容,更多请关注其它相关文章!


# 是一种  # 英文网站外贸seo  # 江西网站优化推广费用  # 深泽海外网站推广报价  # 西藏银川网站推广  # 营销个人微信推广软文  # 线上运营推广整合营销  # 常州seo公司推荐14火星  # 汕头网站推广营销  # 男装电商营销推广规划  # 郑州免费优化网站  # 都要  # ai  # 开闭  # 前提下  # 几个  # 边缘  # 是一个  # 遍历  # 如何实现  # 游戏开发  # 封装性  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: uc手机浏览器网页版入口 uc浏览器手机版便捷登录首页  漫蛙manwa2最新登录网址_漫蛙manwa2手机网页版入口  抖音怎么赚钱_抖音创作者变现方法与途径指南  QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台  QQ邮箱网页版邮箱入口 QQ邮箱官方登录平台  如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!  聚水潭ERP登录页面入口 聚水潭ERP官网登录界面  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  Win11 USB传输速度慢怎么解决 Win11 USB驱动更新与设置  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  苹果手机如何防止被恶意App追踪  Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区  b站如何看历史记录_b站观看历史找回方法  J*aScript中正确使用querySelectorAll与复杂CSS选择器  Python:递归比较文件夹内容并找出特定类型文件的差异  在Blazor WebAssembly应用中动态注入客户端特定指标代码的策略  React Hooks最佳实践:动态组件状态管理的组件化方案  TikTok国际版官网直达_TikTok国际版官网直达进入在线观看  TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法  如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略  必由学官方登录入口 必由学教师学生账号快速访问  c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学  Golang如何使用bytes.Split分割字节切片_Golang bytes切片分割方法  钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法  c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  QQ邮箱登录官网首页 腾讯QQ邮箱网页入口  Golang如何使用const iota_Go iota常量计数器讲解  AO3中文官网链接_AO3网页版稳定镜像站  Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址  印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】  12306选座如何查看座位示意图_12306座位示意图解读与使用  QQ邮箱在线登录平台 QQ邮箱个人邮箱网页版入口  126邮箱账号注册 电脑版登录入口  AO3最新官网入口公告_2025AO3镜像站实时查询方法  Composer如何处理Git子模块(submodule)依赖_Composer与Git Submodule的对比与选择  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  动漫花园资源网使用步骤_动漫花园资源网下载流程  凉拌黄瓜怎么拌更入味 凉拌黄瓜简单家常做法  C#使用XPath查询节点时出错? 常见语法错误与调试技巧  如何仅使用CSS更改登录界面背景图像图标的颜色  Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】  QQ邮箱网页版快速登录 QQ邮箱邮箱账号官方入口地址  J*a里如何实现订单支付与库存同步功能_支付库存同步项目开发方法说明  Angular中父组件异步更新子组件复选框状态的实践指南  微信网页版官方快速登录入口 微信网页版网页版账号直达  解决深度学习模型训练初期异常高损失与完美验证准确率问题  如何在J*a中使用Locale处理多语言环境  如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置  向日葵客户端怎么进行远程CentOS控制_向日葵客户端远程CentOS控制操作教程 

搜索