🧭
一句话理解:访问者把作用于一组稳定对象结构的新操作提取到独立对象中,使新增操作无需修改每个元素类。

它解决什么问题

地图包含敌人、宝箱等不同元素,需要做导出、统计、校验等多种操作。若每种操作都塞进元素类,领域对象会越来越臃肿。访问者把操作集中,并通过双分派选择正确的重载。

C# 示例

遍历对象结构时:
Accept 先根据元素的运行时类型选择方法,再调用访问者对应重载,这就是双分派。

什么时候合适

  • 元素类型较稳定
  • 经常增加横跨所有元素的新操作
  • 操作不属于元素核心职责
例如编辑器校验、导出、统计、调试绘制和报表生成。

主要权衡

新增访问者很容易;新增元素类型很昂贵,因为所有访问者接口和实现都要增加方法。因此,敌人种类频繁增加但操作稳定的系统通常不适合访问者。
访问者还可能要求元素暴露较多数据,削弱封装。可以提供窄查询接口,避免直接公开内部字段。

替代方案

少量类型可用模式匹配;行为属于对象本身时直接放回对象;数据导向结构可使用系统遍历组件数据。

小结

访问者选择的是一种明确的扩展方向:优化“新增操作”,接受“新增元素类型”成本。对象结构足够稳定时,它能让横切操作保持整洁。