迭代器模式(Iterator Pattern)是一种行为设计模式,用于提供一种统一的方法顺序访问聚合对象(如集合、列表、树等)中的元素,而无需暴露其底层数据结构。
迭代器模式,也叫游标模式。它用来遍历集合对象。这里说的“集合对象”,我们也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如,数组、链表、树、图、跳表。
一个完整的迭代器模式,一般会涉及容器和容器迭代器两部分内容。为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。容器中需要定义 iterator() 方法,用来创建迭代器。迭代器接口中需要定义 hasNext()、currentItem()、next() 三个最基本的方法。容器对象通过依赖注入传递到迭代器类中。
遍历集合一般有三种方式:for 循环、foreach 循环、迭代器遍历。后两种本质上属于一种,都可以看作迭代器遍历。相对于 for 循环遍历,利用迭代器来遍历有下面三个优势:
迭代器模式封装集合内部的复杂数据结构,开发者不需要了解如何遍历,直接使用容器提供的迭代器即可;
迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;
迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。
以下从核心概念、结构、优缺点及应用场景等方面详细介绍:
🔍 一、核心概念
目的
通过迭代器对象封装遍历逻辑,实现数据存储与遍历的解耦。客户端只需通过迭代器接口访问元素,无需了解集合的内部结构。关键思想
封装遍历过程:将复杂的遍历算法(如树的中序遍历)独立到迭代器中。
统一访问接口:为不同类型集合(数组、链表等)提供一致的遍历方式。
🧱 二、模式结构(四大角色)
迭代器接口(Iterator)
定义遍历方法:hasNext()
(判断是否有下一元素)、next()
(获取下一元素)。
例:支持Reset()
重置游标或currentItem()
获取当前元素。具体迭代器(Concrete Iterator)
实现迭代器接口,维护遍历状态(如当前索引、游标),并关联具体聚合对象。
例:链表迭代器通过指针移动实现next()
,树迭代器用栈实现深度优先遍历。聚合接口(Aggregate)
声明创建迭代器的方法,如createIterator()
。具体聚合(Concrete Aggregate)
实现聚合接口,管理内部数据集(如List
或数组),并在createIterator()
中返回匹配的迭代器实例。
⚖️ 三、优缺点分析
🛠️ 四、应用场景
复杂数据结构遍历
隐藏树、图等结构的遍历细节(如DFS/BFS),客户端统一调用next()
。统一遍历异构集合
对数组、链表、数据库结果集等提供一致的访问接口。需要多种遍历方式
如音乐播放列表支持顺序播放、随机播放(不同迭代器实现不同算法)。隔离安全与封装
保护集合内部状态(如线程安全集合的迭代器可加锁)。
💡 五、技术实现示例
namespace DesignPatternsPractice.Src.Behavioral.IteratorDesignPattern
{
/// <summary>
/// 迭代器模式
/// </summary>
public class IteratorDesign
{
static void Main()
{
List<string> list = new List<String>
{
{"1"},{"2"},{"3"}
};
ArrayIterator<string> arrayIterator = new ArrayIterator<string>(list);
while (arrayIterator.hasNext())
{
Console.WriteLine("遍历出的元素:" + arrayIterator.currentItem());
arrayIterator.next();
}
}
}
/// <summary>
/// 定义迭代器接口
/// </summary>
/// <typeparam name="E"></typeparam>
public interface Iterator<E>
{
/// <summary>
/// 是否可以继续遍历
/// </summary>
/// <returns></returns>
bool hasNext();
/// <summary>
/// 游标+1
/// </summary>
void next();
/// <summary>
/// 返回游标所指的当前list 中对应的元素
/// </summary>
/// <returns></returns>
E currentItem();
}
public class ArrayIterator<E> : Iterator<E>
{
private int cursor;
private List<E> _arrayList;
public ArrayIterator(List<E> arrayList)
{
cursor = 0;
_arrayList = arrayList;
}
public E currentItem()
{
if (cursor >= _arrayList.Count())
{
throw new Exception("游标大小错误");
}
return _arrayList[cursor];
}
/// <summary>
/// 能否继续遍历
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public bool hasNext()
{
return cursor != _arrayList.Count();
}
public void next()
{
cursor++;
}
}
}
🌐 六、实际应用案例
集合框架:Java的
Iterable
/Iterator
接口,C++ STL中的迭代器。数据库查询:遍历结果集(如JDBC
ResultSet
)。UI组件遍历:GUI框架中遍历窗口内的按钮、文本框等组件。
游戏开发:遍历场景中的实体对象(敌人、道具等)。
💎 总结
迭代器模式通过抽象遍历过程,解决了集合内部结构与客户端遍历逻辑的强耦合问题,是处理复杂数据结构的核心模式之一。其价值在需支持多种遍历方式或异构集合统一访问时尤为突出,但需权衡其在简单场景中的额外设计成本。