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

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

优点:

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 updatevoid 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.mzph.cn/diannao/78910.shtml

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

相关文章

监控docker中的java应用

1)进入指定的容器 docker exec -it demo /bin/bash 2)下载curl root89a67e345354:/# apt install curl -y 3)下载arthas root89a67e345354:/# curl -O https://arthas.aliyun.com/arthas-boot.jar 4)运行 root89a67e345354:/# java -jar arthas-boot.jar 5)监控 […

最新版RubyMine超详细图文安装教程,带补丁包(2025最新版保姆级教程)

目录 前言 一、RubyMine最新版下载 二、RubyMine安装 三、RubyMine补丁 四、运行RubyMine 前言 RubyMine是由JetBrains开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为Ruby和Ruby on Rails开发者设计&#xff0c;提供智能代码补全、调试、测试、版本控制集…

数字政府与智慧城市区别报告分析

数字政府与智慧城市区别报告分析 一、引言 随着信息技术的飞速发展&#xff0c;数字政府和智慧城市成为推动城市现代化和治理能力提升的两个重要概念。虽然它们都依托于信息技术&#xff0c;但二者在目标、内涵、实施路径等方面存在显著差异。本文旨在深入探讨数字政府与智慧…

[MRCTF2020]ezpop wp

本题考点:php反序列化的pop链 首先来了解一下pop链是什么,它类似于多米诺骨牌一环套一环,要调用这个成员方法然后去找能调用这个方法的魔术方法,最后一环接一环,完成一个链子,最终形成payload。 那么来了解一下这些魔术方法 __construct() //类的构造函数&#xff0…

spark架构和RDD相关概念

运行架构&#xff1a; Spark采用master - slave结构&#xff0c;Driver作为master负责作业任务调度&#xff0c;Executor作为slave负责实际执行任务。 核心组件 Driver&#xff1a;执行Spark任务的main方法&#xff0c;将用户程序转化为作业&#xff0c;在Executor间调度任务&…

安全是基石

“安全是基石”这句话强调了安全在个人、企业、社会等各个层面中的基础性和不可替代的重要性。无论是物理安全、网络安全、数据安全&#xff0c;还是生产安全、公共安全&#xff0c;都是保障稳定发展的前提。以下是不同领域中“安全”作为基石的体现&#xff1a; 1. 个人安全 基…

Linux Makefile-概述、语句格式、编写规则、多文件编程、Makefile变量分类:自定义变量、预定义变量

目录 1.make 1.1 make 命令格式 2.Makefile 核心概念‌ ‌ 2.1创建并运行 Makefile步骤 3. Makefile编写 3.1最基础Makefile 3.1.1使用默认make命令 3.1.2使用make -f 命令 3.1.2.1 使用make -f 命令执行默认make操作 3.1.2.2使用 make [ ‐f file ] [ targets ]命令 …

城市应急安防系统EasyCVR视频融合平台:如何实现多源视频资源高效汇聚与应急指挥协同

一、方案背景 1&#xff09;项目背景 在当今数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;视频监控和应急指挥系统在公共安全、城市应急等领域的重要性日益凸显。尤其是在关键场所&#xff0c;高效的视频资源整合与传输能力对于应对突发公共事件、实现快速精准的…

双Token实现用户登录身份认证-Java版

双Token实现用户登录身份认证-Java版 1. 设计方案 方案概述: Access Token: 短期有效的JWT,包含用户ID、设备ID、token版本号。Refresh Token: 长期有效的令牌,存储于Redis,关联用户信息、设备ID及token版本号,用于刷新Access Token。设备绑定: Token与设备ID绑定,防止跨…

Proteus vs Multisim:电路设计与仿真软件对比

Proteus和Multisim作为两款主流的电路设计与仿真软件&#xff0c;在功能定位和应用场景上既有重叠也有显著差异。以下从多个维度综合阐述两者的异同点&#xff1a; 一、相同点 基础功能 ✅ 电路原理图设计&#xff1a;支持电路设计和仿真分析。 ⚙️ 虚拟仪器&#xff1a;提供…

ssh 三级跳

ssh 三级跳 在网络安全和数据传输领域&#xff0c;SSH&#xff08;Secure Shell&#xff09;是一种常用的协议&#xff0c;用于加密两台计算机之间的通信。在某些情况下&#xff0c;你可能需要通过一个中间服务器来间接连接到目标服务器&#xff0c;这通常被称为“三级跳”或“…

Java 性能优化:从原理到实践的全面指南

性能优化是 Java 开发中不可或缺的一环&#xff0c;尤其在高并发、大数据和分布式系统场景下&#xff0c;优化直接影响系统响应速度、资源利用率和用户体验。Java 作为一门成熟的语言&#xff0c;提供了丰富的工具和机制支持性能调优&#xff0c;但优化需要深入理解 JVM、并发模…

【土堆 PyTorch 教程总结】PyTorch入门

目录 一、python学习中两大法宝函数 1、dir() 2、help() 二、PyTorch读取数据集 1、Dataset类 &#xff08;1&#xff09;作用和基本原理 &#xff08;2&#xff09;常见用法 &#xff08;3&#xff09;自定义 Dataset 示例 2、Dataloader类 &#xff08;1&#xff0…

5.DJI-PSDK:Psdk开发负载与Msdk的应用app进行交互:

DJI-PSDK:Psdk开发负载与Msdk的应用app进行交互: 负载设备和无人机使用数据传输模块,在控制命令传输通道上以透传的方式在PSDK和MSDK间传输控制指令。在高速数据传输通道上以透传的方式在PSDK和MSDK间传输数据信息以及用户自定义的数据。使用数据传输功能,不仅可以设置不同…

2025 蓝桥杯省赛c++B组个人题解

声明 本题解为退役蒻苟所写&#xff0c;不保证正确性&#xff0c;仅供参考。 花了大概2个半小时写完&#xff0c;感觉比去年省赛简单&#xff0c;难度大概等价于 codeforces dv4.5 吧 菜鸡不熟悉树上背包&#xff0c;调了一个多小时 题目旁边的是 cf 预测分 所有代码均以通…

Dubbo(53)如何在Spring Boot中集成Dubbo?

在Spring Boot中集成Dubbo可以通过Spring Boot Starter来简化配置&#xff0c;以下是详细的步骤和相关代码示例。 1. 引入依赖 首先&#xff0c;在Spring Boot项目的 pom.xml 中添加Dubbo相关的依赖&#xff1a; <dependencies><!-- Spring Boot Starter --><…

开发一个环保回收小程序需要哪些功能?环保回收小程序

废品分类展示与识别 详细分类列表&#xff1a;清晰展示常见废品类型&#xff0c;如废纸&#xff08;报纸、书本纸、包装纸等&#xff09;、塑料&#xff08;塑料瓶、塑料容器、塑料薄膜等&#xff09;、金属&#xff08;易拉罐、铁制品、铜制品等&#xff09;、玻璃&#xff0…

抗干扰CAN总线通信技术在分布式电力系统中的应用

摘要&#xff1a;随着分布式电力系统的广泛应用&#xff0c;其通信系统的可靠性与稳定性受到了前所未有的挑战。CAN总线通信技术以其卓越的抗干扰性能和可靠性&#xff0c;在众多通信技术中脱颖而出&#xff0c;成为解决分布式电力系统通信问题的关键。本文深入剖析了CAN总线通…

MySQL与Oracle深度对比

MySQL与Oracle深度对比&#xff1a;数据类型与SQL差异 一、数据类型差异 1. 数值类型对比 数据类型MySQLOracle整数TINYINT, SMALLINT, MEDIUMINT, INT, BIGINTNUMBER(精度) 或直接INT(内部仍为NUMBER)小数DECIMAL(p,s), FLOAT, DOUBLENUMBER(p,s), FLOAT, BINARY_FLOAT, BI…

探索 Rust 语言:高效、安全与并发的完美融合

在当今的编程语言领域&#xff0c;Rust 正以其独特的魅力吸引着越来越多开发者的目光。它诞生于 Mozilla 实验室&#xff0c;旨在解决系统编程中长久以来存在的难题&#xff0c;如今已成为构建可靠、高效软件的有力工具。 1 内存安全 Rust 通过所有权&#xff08;ownership&a…