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

news2025/4/15 18:37:29

访问者模式是一种行为设计模式,它允许在不改变对象结构的前提下,定义作用于这些对象元素的新操作

优点:

1.​​符合开闭原则:新增操作只需添加新的访问者类,无需修改现有对象结构。
​​2.操作逻辑集中管理​​:将相关操作聚合在同一个访问者中,避免代码分散。
​​3.支持跨对象计算​​:通过遍历对象结构,实现跨元素的全局计算。
​​4.增强代码可读性​​:操作逻辑与数据结构分离,代码结构更易维护。如渲染、战斗伤害、AI决策等不同模块的代码独立为不同访问者。

缺点:

1.破坏对象封装性​:访问者需要直接访问对象内部状态,强制暴露私有字段或方法。
优化:​​1.接口隔离,通过显式接口限制访问范围。
2.元素类型扩展困难:新增元素类型(如新增NPC类)需修改所有访问者接口和实现。
优化:1.​访问者适配器模式​​:通过中间适配器隔离变化。
3.性能损耗​​:频繁创建访问者对象导致性能下降。
优化:1.​访问者对象池​​:复用访问者实例减少GC压力。2.批处理模式:​​合并多次访问为单次遍历。3.静态委托优化​​:通过预编译减少虚方法调用开销。
4.复杂对象结构支持弱​​:对嵌套结构(如树形结构的场景节点)访问逻辑复杂。
优化:1.​​组合模式集成:​​将复杂结构抽象为组合元素。2.访问者责任链:​​拆分复杂操作为多个子访问者链式处理:

说明例子:

1.UML类图:
2.实现:

1.定义图基类:

    public abstract class IGraph
    {
        public abstract void Draw(); //绘制
        public abstract float GetArea();  //获取面积
        public abstract int GetVectorCount(); //获取顶点数
        public abstract void RunVisitor(IGraphVisitor theVisitor);
    }

2.定义访问者基类:

    public abstract class IGraphVisitor
    {
        //由Cicle类来调用
        public virtual void VisitCicle(CicleGraph theCicle) { }

        //由Rectangle类调用
        public virtual void VisitRectangle(RectangleGraph theRect) { }
        
        //由Triangle类调用
        public virtual void VisitTriangle(TriangleGraph theTriangle) { }
    }

3.定义容器类:

  public class GraphContainer
  {
      List<IGraph> m_Graphs = new List<IGraph>();

      public GraphContainer() { }

      //新增
      public void AddShape(IGraph graph)
      {
          m_Graphs.Add(graph);
      }
       
      //共享的访问者接口
      public void RunVisitor(IGraphVisitor theVisitor)
      {
          foreach (IGraph graph in m_Graphs)
          {
              graph.RunVisitor(theVisitor);
          }
      }
  }

4.定义具体图形类:

    public class CicleGraph : IGraph
    {
        public override void Draw()
        {
            Debug.Log("Draw CicleGraph...");
        }

        public override int GetVectorCount()
        {
            return 9999;
        }

        public override float GetArea()
        {
            return Mathf.PI * 5 * 5;
        }

        public override void RunVisitor(IGraphVisitor theVisitor)
        {
            theVisitor.VisitCicle(this);
        }
    }

    public class RectangleGraph : IGraph
    {
        public override void Draw()
        {
            Debug.Log("Draw RectangleGraph...");
        }

        public override int GetVectorCount()
        {
            return 4;
        }

        public override float GetArea()
        {
            return 4 * 5;
        }

        public override void RunVisitor(IGraphVisitor theVisitor)
        {
            theVisitor.VisitRectangle(this);
        }
    }

    public class TriangleGraph : IGraph
    {
        public override void Draw()
        {
            Debug.Log("Draw TriangleGraph...");
        }

        public override int GetVectorCount()
        {
            return 3;
        }

        public override float GetArea()
        {
            return .5f * 3 * 5;
        }

        public override void RunVisitor(IGraphVisitor theVisitor)
        {
            theVisitor.VisitTriangle(this);
        }
    }

5.定义具体访问者类:

    public class DrawVisitor : IGraphVisitor
    {
        public override void VisitCicle(CicleGraph theCicle)
        {
            theCicle.Draw();
        }

        public override void VisiRectangle(RectangleGraph theRect)
        {
            theRect.Draw();
        }

        public override void VisitTriangle(TriangleGraph theTriangle)
        {
            theTriangle.Draw();
        }
    }

    public class VertexCountVisitor : IGraphVisitor
    {
        public int Count = 0;

        //由Cicle类调用
        public override void VisitCicle(CicleGraph theCicle)
        {
            Count = theCicle.GetVectorCount();
            Debug.Log("VisitCicle Count:" + Count);
        }

        //由Rectangle类调用
        public override void VisitRectangle(RectangleGraph theRect)
        {
            Count += theRect.GetVectorCount();
            Debug.Log("VisitRectangle Count:" + Count);
        }

        //由Triangle类调用
        public override void VisitTriangle(TriangleGraph theTriangle)
        {
            Count += theTriangle.GetVectorCount();
            Debug.Log("VisitTriangle Count:" + Count);
        }
    }

    public class CicleAreaVisitor : IGraphVisitor
    {
        public float Area;

        //由Sphere类来调用
        public override void VisitCicle(CicleGraph theCicle)
        {
            Area += theCicle.GetArea();
            Debug.Log("VisitCicle Area:" + Area);
        }
    }

6.测试: 

    public class VisitorPattern : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            GraphContainer graphContainer = new GraphContainer();

            graphContainer.AddShape(new CicleGraph());
            graphContainer.AddShape(new RectangleGraph());
            graphContainer.AddShape(new TriangleGraph());

            graphContainer.RunVisitor(new DrawVisitor());

            graphContainer.RunVisitor(new VertexCountVisitor());

            graphContainer.RunVisitor(new CicleAreaVisitor());
        }
    }

游戏中使用场景:

1.战斗系统:​​计算不同角色(玩家、敌人)之间的伤害。
​​2.存档系统:​​序列化不同类型的游戏对象状态。
​​3.渲染优化:​​根据对象类型选择渲染策略(如LOD、材质替换)。
​​4.AI行为决策:​​根据场景元素类型生成不同的AI反应。
​​5.成就系统​:​检测特定游戏对象的状态变化(如击杀稀有敌人)。

总结:

在游戏开发中,访客模式特别适合需要跨多种对象类型执行统一逻辑的场景​​,如战斗计算、存档系统和数据分析模块。

参考书籍或链接:

C# 常用设计模式 (refactoringguru.cn)

《Hands-On Game Development Patterns with Unity 2019》

《设计模式与游戏完美开发》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HashTable,HashMap,ConcurrentHashMap之间的区别

文章目录 线程安全方面性能方面总结 线程安全方面 HashMap线程不安全&#xff0c;HashMap的方法没有进行同步&#xff0c;多个线程同时访问HashMap&#xff0c;并至少有一个线程修改了其内容&#xff0c;则必须手动同步。 HashTable是线程安全的&#xff0c;在HashMap的基础上…

LeetCode.225. 用队列实现栈

用队列实现栈 题目解题思路1. push2. pop3. empty CodeQueue.hQueue.cStack.c 题目 225. 用队列实现栈 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现…

LVGL AnalogClock控件和Dclock控件详解

LVGL AnalogClock控件和Dclock控件详解 一、AnalogClock控件详解1. 概述2. 创建模拟时钟2.1 函数2.2 参数2.3 返回值 3. 设置时间3.1 函数3.2 参数 4. 获取时间4.1 函数4.2 参数 5. 设置样式5.1 常用样式属性5.2 示例代码 6. 更新时间6.1 定时器回调示例6.2 创建定时器 7. 示例…

【C++初学】课后作业汇总复习(七) 指针-深浅copy

1、 HugeInt类:构造、、cout Description: 32位整数的计算机可以表示整数的范围近似为&#xff0d;20亿到&#xff0b;20亿。在这个范围内操作一般不会出现问题&#xff0c;但是有的应用程序可能需要使用超出上述范围的整数。C可以满足这个需求&#xff0c;创建功能强大的新的…

探索加密期权波动率交易的系统化实践——动态对冲工具使用

Trading Volatility – What Are My Options? 在本文中&#xff0c;我们将介绍一些如何交易资产波动性&#xff08;而非资产价格&#xff09;的示例。为了帮助理解&#xff0c;我们将使用 Deribit 上提供的几种不同产品&#xff0c;包括但不限于期权。我们将尽可能消除对标的价…

方案精读:51页 财政数据信息资源目录数据标准存储及大数据资产化规划方案【附全文阅读】

该方案聚焦财政数据信息资源管理,适用于财政部门工作人员、数据管理与分析人员以及关注财政大数据应用的相关人士。 方案旨在构建财政数据资源目录,推动大数据在财政领域的应用与落地。整体规划上,以 “金财工程” 应用支撑平台为基础,建立省、市、县三级目录体系,遵循相关…

开源实时语音交互大模型Ultravox-cn

一款为实时语音交互设计的快速多模态LLM 概述 Ultravox是一种新型的多模态LLM&#xff0c;能够理解文本和人类语音&#xff0c;无需单独的自动语音识别&#xff08;ASR&#xff09;阶段。基于AudioLM、SeamlessM4T、Gazelle、SpeechGPT等研究&#xff0c;Ultravox能够将任何…

基于web的民宿信息系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着信息时代的来临&#xff0c;民宿过去的民宿信息方式的缺点逐渐暴露&#xff0c;对过去的民宿信息的缺点进行分析&#xff0c;采取计算机方式构建民宿信息系统。本文通过阅读相关文献&#xff0c;研究国内外相关技术&#xff0c;提出了一种民宿信息管理、民宿信息管理…

04-微服务 面试题-mk

文章目录 1.Spring Cloud 常见的组件有哪些?2.服务注册和发现是什么意思?(Spring Cloud 如何实现服务注册发现)3.Nacos配置中心热加载实现原理及关键技术4.OpenFeign在微服务中的远程服务调用工作流程5.你们项目负载均衡如何实现的 ?6.什么是服务雪崩,怎么解决这个问题?…

【Linux篇】深入理解文件系统:从基础概念到 ext2 文件系统的应用与解析

文件系统的魔法&#xff1a;让计算机理解并存储你的数据 一. 文件系统1.1 块1.2 分区1.3 inode(索引节点) 二. ext2文件系统2.1 认识文件系统2.2 Block Group (块组)2.2.1 Block Group 的基本概念2.2.2 Block Group 的作用 2.3 块组内部结构2.3.1 超级块&#xff08;Super Bloc…

C++STL——容器-list(含模拟实现,即底层原理)(含迭代器失效问题)(所有你不理解的问题,这里都有解答,最详细)

目录 1.迭代器的分类 2.list的使用 2.1 list的构造 2.2 list iterator 2.3 list capacity 2.4 list element access ​编辑 2.5 list modifiers ​编辑2.5.1 list插入和删除 2.5.2 insert /erase 2.5.3 resize/swap/clear ​编辑 2.6 list的一些其他接口…

计算机组成原理笔记(十五)——3.5指令系统的发展

不同类型的计算机有各具特色的指令系统&#xff0c;由于计算机的性能、机器结构和使用环境不同&#xff0c;指令系统的差异也是很大的。 3.5.1 x86架构的扩展指令集 x86架构的扩展指令集是为了增强处理器在多媒体、三维图形、并行计算等领域的性能而设计的。这些扩展指令集通…

基于时间序列分解与XGBoost的交通通行时间预测方法解析

一、问题背景与数据概览 在城市交通管理系统中,准确预测道路通行时间对于智能交通调度和路径规划具有重要意义。本文基于真实道路传感器数据,构建了一个结合时间序列分解与机器学习模型的预测框架。数据源包含三个核心部分: 道路通行数据(new_gy_contest_traveltime_train…

基于XGBoost的异烟酸生产收率预测:冠军解决方案解析

1. 引言 在化工生产领域,准确预测产品收率对优化工艺流程、降低生产成本具有重要意义。本文以异烟酸生产为研究对象,通过机器学习方法构建预测模型,在包含10个生产步骤、42个工艺参数的数据集上实现高精度收率预测。该方案在工业竞赛中斩获冠军,本文将深度解析其技术实现细…

计算机视觉算法实现——电梯禁止电瓶车进入检测:原理、实现与行业应用(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 电梯安全检测领域概述 近年来&#xff0c;随着电动自行车&#xff08;以下简称"电瓶车"&…

MOM成功实施分享(八)汽车活塞生产制造MOM建设方案(第二部分)

在制造业数字化转型的浪潮中&#xff0c;方案对活塞积极探索&#xff0c;通过实施一系列数字化举措&#xff0c;在生产管理、供应链协同、质量控制等多个方面取得显著成效&#xff0c;为行业提供了优秀范例。 1.转型背景与目标&#xff1a;活塞在数字化转型前面临诸多挑战&…

Azure AI Foundry 正在构建一个技术无障碍的未来世界

我们习以为常的街道和数字世界&#xff0c;往往隐藏着被忽视的障碍——凹凸不平的路面、不兼容的网站、延迟的字幕或无法识别多样化声音的AI模型。这些细节对某些群体而言&#xff0c;却是日常的挑战。正如盲道不仅帮助视障者&#xff0c;也优化了整体城市体验&#xff0c;信息…

地毯填充luogu

P1228 地毯填补问题 题目描述 相传在一个古老的阿拉伯国家里,有一座宫殿。宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子上,只要谁能用地毯将除公主站立的地方外的所有地方盖上,美丽漂亮聪慧的公主就是他的人了。公主…

哈喽打车 小程序 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向过程 这一次遇到这种风控感觉挺有…

基于 Vue 3 + Express 的网盘资源搜索与转存工具,支持响应式布局,移动端与PC完美适配

一个基于 Vue 3 Express 的网盘资源搜索与转存工具&#xff0c;支持响应式布局&#xff0c;移动端与PC完美适配&#xff0c;可通过 Docker 一键部署。 功能特性 &#x1f50d; 多源资源搜索 支持多个资源订阅源搜索支持关键词搜索与资源链接解析支持豆瓣热门榜单展示 &#…