文章目录
🔄 迭代器模式(Iterator Pattern)深度解析
——以Unity实现高效集合遍历与动态场景管理为核心案例
一、模式本质与核心价值
核心目标:
✅ 统一集合遍历接口,无需暴露内部数据结构
✅ 支持多种遍历方式(顺序、逆序、过滤等)
✅ 解耦集合结构与遍历算法,提升代码扩展性
关键术语:
- Iterator(迭代器接口):定义遍历操作(Next、HasNext等)
- ConcreteIterator(具体迭代器):实现特定遍历逻辑
- Aggregate(聚合接口):定义创建迭代器的方法
- ConcreteAggregate(具体聚合):实现集合数据结构
数学表达:
设集合C有元素{e₁, e₂, …, eₙ},迭代器I满足:
I© → e₁ → e₂ → … → eₙ
二、经典UML结构
三、Unity实战代码(背包系统遍历)
1. 定义迭代器与聚合接口
public interface IIterator<T> {
bool HasNext();
T Next();
void Reset();
}
public interface IAggregate<T> {
IIterator<T> CreateIterator();
int Count { get; }
T this[int index] { get; }
}
2. 实现具体聚合类(背包物品集合)
public class Inventory : IAggregate<Item> {
private List<Item> _items = new();
public void AddItem(Item item) => _items.Add(item);
public IIterator<Item> CreateIterator() => new InventoryIterator(this);
public int Count => _items.Count;
public Item this[int index] => _items[index];
}
3. 实现具体迭代器
public class InventoryIterator : IIterator<Item> {
private Inventory _inventory;
private int _index;
public InventoryIterator(Inventory inventory) {
_inventory = inventory;
_index = -1;
}
public bool HasNext() => _index < _inventory.Count - 1;
public Item Next() => _inventory[++_index];
public void Reset() => _index = -1;
}
4. 客户端使用
public class InventoryUI : MonoBehaviour {
[SerializeField] private Inventory _inventory;
void Update() {
if(Input.GetKeyDown(KeyCode.I)) {
StartCoroutine(DisplayItems());
}
}
private IEnumerator DisplayItems() {
var iterator = _inventory.CreateIterator();
while(iterator.HasNext()) {
Item item = iterator.Next();
Debug.Log($"物品:{item.Name}");
yield return null; // 分帧显示避免卡顿
}
}
}
四、模式进阶技巧
1. 过滤迭代器(按类型遍历)
public class WeaponIterator : IIterator<Item> {
private IIterator<Item> _baseIterator;
public WeaponIterator(Inventory inventory) {
_baseIterator = inventory.CreateIterator();
}
public bool HasNext() {
while(_baseIterator.HasNext()) {
if(_baseIterator.Next() is Weapon) {
_baseIterator.ResetToPrevious();
return true;
}
}
return false;
}
public Item Next() => _baseIterator.Next();
}
2. 协程分帧遍历
public static class IteratorExtensions {
public static IEnumerator CoIterate<T>(this IIterator<T> iterator, Action<T> action) {
while(iterator.HasNext()) {
action(iterator.Next());
yield return null; // 每帧处理一个元素
}
}
}
// 使用示例
StartCoroutine(_inventory.CreateIterator().CoIterate(item => {
// 处理每个物品
}));
3. 双向迭代器
public interface IBidirectionalIterator<T> : IIterator<T> {
bool HasPrevious();
T Previous();
}
public class InventoryBidirectionalIterator : IBidirectionalIterator<Item> {
// 实现前后遍历逻辑
}
五、游戏开发典型应用场景
场景对象管理
public class SceneObjectManager : IAggregate<GameObject> { private List<GameObject> _objects = new(); public IIterator<GameObject> CreateIterator() => new SceneObjectIterator(this); }
技能效果链
public class SkillEffectChain : IAggregate<IEffect> { public IIterator<IEffect> CreateReverseIterator() { return new ReverseEffectIterator(this); } }
AI决策评估
public class AIEvaluator { public void EvaluateAll(IIterator<AICondition> conditions) { while(conditions.HasNext()) { var condition = conditions.Next(); condition.Evaluate(); } } }
动态生成系统
public class WorldGenerator { public void GenerateChunks(IIterator<Vector3> positionIterator) { while(positionIterator.HasNext()) { GenerateChunkAt(positionIterator.Next()); } } }
六、性能优化策略
策略 | 实现方式 | 适用场景 |
---|---|---|
批处理迭代 | 每次处理多个元素 | 大规模数据集 |
缓存迭代器 | 复用迭代器实例 | 频繁遍历操作 |
惰性求值 | 需要时再计算元素 | 复杂对象集合 |
空间分区 | 结合四叉树/八叉树 | 3D场景遍历 |
七、模式对比与选择
维度 | 迭代器模式 | 访问者模式 |
---|---|---|
关注点 | 遍历机制 | 数据操作 |
扩展性 | 新增迭代方式 | 新增操作类型 |
数据结构耦合 | 低耦合 | 需要接受访问者接口 |
典型场景 | 集合遍历 | 复杂数据结构操作 |
八、最佳实践原则
- 单一职责原则:迭代器只关注遍历逻辑
- 不可变快照:在迭代过程中防止集合修改
public class SnapshotIterator<T> : IIterator<T> { private readonly T[] _snapshot; // 基于快照的迭代实现... }
- 异常处理:处理边界条件
public T Next() { if(!HasNext()) throw new InvalidOperationException("No more elements"); // ... }
- 资源释放:实现IDisposable接口
public class FileLineIterator : IIterator<string>, IDisposable { private StreamReader _reader; public void Dispose() => _reader?.Dispose(); }
九、常见问题解决方案
Q1:如何避免遍历时集合被修改?
→ 使用读写锁或副本迭代
public class ThreadSafeIterator<T> : IIterator<T> {
private ReaderWriterLockSlim _lock;
// 在Next/HasNext中加读锁...
}
Q2:如何实现复杂条件过滤?
→ 使用组合过滤器
public class CompositeFilterIterator<T> : IIterator<T> {
private List<Predicate<T>> _filters = new();
public void AddFilter(Predicate<T> filter) {
_filters.Add(filter);
}
public bool HasNext() {
while(_baseIterator.HasNext()) {
var item = _baseIterator.Peek();
if(_filters.All(f => f(item))) return true;
_baseIterator.Next();
}
return false;
}
}
Q3:如何优化大型场景遍历性能?
→ 实现空间分区迭代器
public class QuadTreeIterator : IIterator<GameObject> {
private QuadTree _quadTree;
private List<QuadTreeNode> _nodeStack = new();
public bool HasNext() {
while(_nodeStack.Count > 0) {
var current = _nodeStack.Last();
if(current.HasChildren) {
// 处理子节点...
} else {
return current.Objects.Count > 0;
}
}
return false;
}
}
上一篇 【行为型之解释器模式】游戏开发实战——Unity动态公式解析与脚本系统的架构奥秘
下一篇 【行为型之中介者模式】游戏开发实战——Unity复杂系统协调与通信架构的核心秘诀