当前位置: 首页 > news >正文

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

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

优点:

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》

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

相关文章:

  • 【LeetCode】算法详解#4 ---合并区间
  • 进程线程回顾
  • Pinia最基本用法
  • Nginx基础讲解
  • ros2-rviz2控制unity仿真的6关节机械臂,探索从仿真到实际应用的过程
  • 论文精度:HeightFormer:基于Transformer的体素高度预测在路边3D目标检测中的应用
  • flutter 桌面应用之右键菜单
  • 【Cursor 】Cursor 安装与配置指南:从零开始的高效开发之旅
  • QT6 源(16):存储 QT 里元对象的类信息的类 QMetaClassInfo 的类,只有两个成员函数 name()、value(),比元对象属性简单多了
  • 数据驱动,数字能量分析API助力手机号数据解读
  • RAG Fusion技术详解与应用场景
  • 趣味编程之Spring的白学之路
  • 二、Android Studio环境安装
  • [React] 如何用 Zustand 构建一个响应式 Enum Store?附 RTKQ 实战与 TS 架构落地
  • 波束形成(BF)从算法仿真到工程源码实现-第七节-关于波束10个基本概念
  • Jenkins 发送钉钉消息
  • 前端jest(vitest)单元测试快速手上
  • Redis基础知识:
  • 解释:指数加权移动平均(EWMA)
  • C++ 编程指南36 - 使用Pimpl模式实现稳定的ABI接口
  • 当“小铁人”遇上青浦,看00后如何玩转长三角铁三
  • 病愈出院、跳大神消灾也办酒,新华每日电讯:农村滥办酒席何时休
  • 首次公布!我国空间站内发现微生物新物种
  • 美国将与阿联酋合作建立海外最大的人工智能数据中心
  • 全国人大常委会今年将初次审议检察公益诉讼法
  • 哪种“网红减肥法”比较靠谱?医学专家和运动专家共同解答