欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 从C++编程入手设计模式——访问者模式

从C++编程入手设计模式——访问者模式

2025/6/24 0:02:43 来源:https://blog.csdn.net/charlie114514191/article/details/148821731  浏览:    关键词:从C++编程入手设计模式——访问者模式

从C++编程入手设计模式——访问者模式

​ 在软件开发中,我们常常会面对这样的场景:某一组对象是稳定的,但我们希望对它们执行不同的操作,比如打印信息、计算总和、导出数据等。访问者模式就是为了解决这种需求而出现的。

​ 访问者模式的核心思想是把操作从对象本身分离出去。对象只负责结构,而访问者负责逻辑。这样,当我们需要添加新的操作时,只需要新增一个访问者类,而不需要去改动原有的对象定义。这是一种典型的“对修改关闭,对扩展开放”的设计方式。

我们以一个简单的图形示例说明访问者的基本组成:

[Circle]         [Rectangle]        [Triangle]|                  |                  || accept(visitor)  | accept(visitor)  | accept(visitor)↓                  ↓                  ↓visitor.visit(this) visitor.visit(this) visitor.visit(this)↓↓↓[AreaCalculator]

每个图形只需要调用 accept(visitor),然后让访问者自己决定要对该图形干什么。图形不关心访问者的行为,访问者也不关心图形的其他内部结构,它只处理它理解的部分。

访问者与其他模式的对比

一些同志会把访问者模式和策略模式或命令模式搞混,下面我们做一些简要的比较。

与策略模式的对比

策略模式是“对象自己决定调用哪个策略”。例如一个排序器对象,它可以选择使用冒泡或快排。这个行为是封装在策略对象里的,由调用者自己选择。

访问者模式则是“结构体让外部访问者决定行为”。对象不会自己决定使用什么逻辑,它只是说“欢迎你来访问我”。

比较项策略模式访问者模式
核心目标动态切换算法或行为抽离并扩展对象结构的操作逻辑
典型行为发起者客户端被访问的对象结构
对象结构变化支持不支持(结构变更需改全部访问者)
与命令模式的对比

命令模式是把动作抽象为命令对象,比如“打印”、“撤销”,客户端持有命令并在合适的时候执行。

访问者模式则关注于遍历对象结构,执行与对象类型强相关的逻辑。一个命令可以作用于很多对象;而访问者是在遍历结构时,进行特定逻辑处理。


C++ 中的双重分派机制

访问者模式有一个典型的特性叫“双重分派”(Double Dispatch)。通俗来说,它的流程是这样的:

shape->accept(visitor);
↓
visitor.visit(*this);

第一次是形如:

void Circle::accept(ShapeVisitor& v) { v.visit(*this); }

而访问者又定义了多个重载:

void visit(Circle& c);
void visit(Rectangle& r);
void visit(Triangle& t);

在 C++ 中,我们通过虚函数机制实现第一次分派,通过函数重载 + 类型引用来实现第二次分派。这种机制看起来有点拐弯,但正因为如此,访问者才能根据运行时对象的真实类型执行不同逻辑。


访问者变体设计

访问者模式本身也有一些典型的变种设计,下面列出几个常见场景。

1. 返回值访问者

我们可以让访问者返回值,例如在计算表达式时返回结果:

struct Evaluator : ExprVisitor {int result = 0;void visit(AddExpr& e) override {e.left->accept(*this);int l = result;e.right->accept(*this);int r = result;result = l + r;}
};

每一步通过成员变量 result 暂存递归过程的值。

2. 多访问者组合

有时我们需要多个访问者协作,例如一个打印器 + 日志器 + 导出器,可以统一封装为“访问者链”,逐个调用:

[Shape]↓
[Printer] -> [Logger] -> [Exporter]

这类似于责任链的组合,用于把多种行为分开而不耦合。


适用场景总结

访问者模式适用于以下几种场景:

  1. 数据结构稳定,行为变化频繁。
  2. 需要对对象结构进行“集中式处理”,比如统一导出。
  3. 需要多个逻辑处理过程而不破坏类本身。

常见应用场景包括:

  • 编译器中的 AST(抽象语法树)处理器
  • 报表生成系统(访问各类统计数据)
  • 文件结构扫描器(文件夹、文件的遍历)
  • UI 渲染树分析器

练习题:几何图形面积计算器

题目描述:
定义一组几何图形(如:圆形 Circle、矩形 Rectangle、三角形 Triangle),使用访问者模式实现一个面积计算器,使得添加新的图形时无需修改已有的访问者逻辑。

要求:

  1. 所有图形类实现一个抽象基类 Shape,具有 accept(Visitor&) 方法。
  2. 定义一个 ShapeVisitor 抽象类,并由其派生 AreaCalculatorVisitor 实现面积计算逻辑。
  3. 添加一个主函数中构造多个图形并调用访问者进行面积统计。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词