Unity迭代器模式

1.背景介绍

假如现在我有一个怪物脚本和学生脚本,里面分别存放了所有的怪物和所有的学生,但是怪物和学生一个用的数组存一个用的字典存,如果我想打印出所有的学生和所有的怪物ID,先看看不使用迭代器的方式。

怪物管理脚本

cs 复制代码
public class MonsterManage
{
    public int[] Allmonsters = { 1001, 1002, 1003, 1004, 1005 };
}

学生管理脚本

cs 复制代码
public class StudentManage
{
    public Dictionary<string, int> ALlstudents = new Dictionary<string, int>()
    {
        { "张三", 18 },
        { "李四", 20 },
        { "王五", 22 },
        { "赵六", 19 },
        { "孙七", 21 },
        { "周八", 17 },
        { "吴九", 23 },
        { "郑十", 20 },
        { "钱十一", 18 },
        { "郑十二", 22 }
    };
}

使用脚本

cs 复制代码
public class Usertext : MonoBehaviour
{
    void Start()
    {
        StudentManage students = new();
        MonsterManage monsters = new();
        //遍历学生
        foreach (var student in students.ALlstudents)
        {
            Debug.Log("学生学号"+student.Value);
        }
        //遍历怪物
        for (int i = 0; i < monsters.Allmonsters.Length; i++)
        {
            Debug.Log("怪物id" + monsters.Allmonsters[i]);
        }
    }
}

可以看到我们打印的时候每次都必须要知道对方的数据结构才能够遍历。下面是迭代器模式。

1.迭代器接口

里面很简单,就两个方法,HasNext告诉外部我后面还有没有值,Next将遍历出的对象返回出去。

cs 复制代码
public interface IIterator<T>
{
    bool HasNext();
    T Next();
}

2.怪物迭代器

cs 复制代码
public class MonsterIterator : IIterator<int>
{
    private int[] monsters;
    private int index = 0;

    public MonsterIterator(int[] monsters)
    {
        this.monsters = monsters;
    }

    public bool HasNext()
    {
        return index < monsters.Length;
    }

    public int Next()
    {
        return monsters[index++];
    }
}

在怪物脚本中添加迭代器的创建方法。

cs 复制代码
public class MonsterManage
{
    public int[] Allmonsters = { 1001, 1002, 1003, 1004, 1005 };

    //封装迭代器的创建方法
    public IIterator<int> CreateIterator()
    {
        return new MonsterIterator(Allmonsters);
    }
}

3.学生迭代器

cs 复制代码
using System.Collections.Generic;

public class StudentIterator : IIterator<KeyValuePair<string, int>>
{
    //创建一个可枚举的学生字典
    private IEnumerator<KeyValuePair<string, int>> enumerator;

    public StudentIterator(Dictionary<string, int> students)
    {
        enumerator = students.GetEnumerator();
    }

    public bool HasNext()
    {
        //移动到下一个元素
        return enumerator.MoveNext();
    }

    public KeyValuePair<string, int> Next()
    {
        //返回当前元素
        return enumerator.Current;
    }
}

在学生脚本中添加迭代器的创建方法。

cs 复制代码
public class StudentManage
{
    public Dictionary<string, int> ALlstudents = new Dictionary<string, int>()
    {
        { "张三", 18 },
        { "李四", 20 },
        { "王五", 22 },
        { "赵六", 19 },
        { "孙七", 21 },
        { "周八", 17 },
        { "吴九", 23 },
        { "郑十", 20 },
        { "钱十一", 18 },
        { "郑十二", 22 }
    };
    //封装迭代器的创建方法
    public IIterator<KeyValuePair<string, int>> CreateIterator()
    {
        return new StudentIterator(ALlstudents);
    }
}

4.使用

现在我们就能以同样的方式使用遍历了。

cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Usertext : MonoBehaviour
{
    void Start()
    {
        StudentManage students = new();
        MonsterManage monsters = new();

        // 遍历学生
        var studentIterator = students.CreateIterator();
        while (studentIterator.HasNext())
        {
            var student = studentIterator.Next();
            Debug.Log("学生学号 " + student.Value);
        }

        // 遍历怪物
        var monsterIterator = monsters.CreateIterator();
        while (monsterIterator.HasNext())
        {
            int monsterId = monsterIterator.Next();
            Debug.Log("怪物id " + monsterId);
        }
    }
}

5.运行结果

将Usertext挂载到场景中的一个空对象上然后运行游戏,可以看到我们的遍历结果打印了出来。

总结

当需要遍历的集合内部结构较为复杂,或者未来可能频繁发生变化时,与其让使用者关心"数据是怎么存的",不如通过迭代器模式统一对外的访问方式。

迭代器模式将"遍历规则"封装在内部,使外部代码只需要关心"是否还有下一个元素"和"当前元素是什么",从而实现遍历逻辑与业务逻辑的解耦。

在实际项目中,这种设计不仅能降低代码耦合度,也能让系统在扩展和维护时更加从容。

相关推荐
玉夏1 天前
【Shader基础】ShaderLab 语法
unity·游戏引擎
一天 24h1 天前
Python自定义迭代器:从入门到精通
开发语言·python·迭代器模式·学习方法·新人首发
WarPigs1 天前
Unity部署MessagePack
unity·游戏引擎
人月神话-Lee1 天前
【图像处理】框架设计——协议、值类型与工程化思维
图像处理·人工智能·ios·设计模式·架构·ai编程·swift
☆平常心☆1 天前
Unity插件MagicLightmapSwitcher修改灯光强度大于100
unity·游戏引擎
AI大法师1 天前
Xbox回归经典绿
大数据·设计模式·xbox
老码观察1 天前
设计模式实战解读(六):装饰器模式——功能增强,不动原代码
java·设计模式·装饰器模式
平行云2 天前
实时云渲染预启动技术解析:UE数字孪生应用的延迟优化机制(二)
linux·unity·ue5·webgl·实时云渲染·云桌面·像素流
Doris_20232 天前
代码格式化 使用oxfmt
设计模式·架构·前端框架