迭代器模式(Iterator Pattern)是一种​​行为设计模式​​,用于提供一种统一的方法顺序访问聚合对象(如集合、列表、树等)中的元素,而无需暴露其底层数据结构。

迭代器模式,也叫游标模式。它用来遍历集合对象。这里说的“集合对象”,我们也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如,数组、链表、树、图、跳表。

一个完整的迭代器模式,一般会涉及容器和容器迭代器两部分内容。为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。容器中需要定义 iterator() 方法,用来创建迭代器。迭代器接口中需要定义 hasNext()、currentItem()、next() 三个最基本的方法。容器对象通过依赖注入传递到迭代器类中。

遍历集合一般有三种方式:for 循环、foreach 循环、迭代器遍历。后两种本质上属于一种,都可以看作迭代器遍历。相对于 for 循环遍历,利用迭代器来遍历有下面三个优势:

  • 迭代器模式封装集合内部的复杂数据结构,开发者不需要了解如何遍历,直接使用容器提供的迭代器即可;

  • 迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;

  • 迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。

以下从核心概念、结构、优缺点及应用场景等方面详细介绍:


🔍 一、核心概念

  1. ​目的​
    通过迭代器对象封装遍历逻辑,实现​​数据存储与遍历的解耦​​。客户端只需通过迭代器接口访问元素,无需了解集合的内部结构。

  2. ​关键思想​

    • ​封装遍历过程​​:将复杂的遍历算法(如树的中序遍历)独立到迭代器中。

    • ​统一访问接口​​:为不同类型集合(数组、链表等)提供一致的遍历方式。


🧱 二、模式结构(四大角色)

  1. ​迭代器接口(Iterator)​
    定义遍历方法:hasNext()(判断是否有下一元素)、next()(获取下一元素)。
    例:支持Reset()重置游标或currentItem()获取当前元素。

  2. ​具体迭代器(Concrete Iterator)​
    实现迭代器接口,维护遍历状态(如当前索引、游标),并关联具体聚合对象。
    例:链表迭代器通过指针移动实现next(),树迭代器用栈实现深度优先遍历。

  3. ​聚合接口(Aggregate)​
    声明创建迭代器的方法,如createIterator()

  4. ​具体聚合(Concrete Aggregate)​
    实现聚合接口,管理内部数据集(如List或数组),并在createIterator()中返回匹配的迭代器实例。


⚖️ 三、优缺点分析

​​优点​​

​​缺点​​

✅ ​​解耦遍历与集合​​:避免客户端依赖具体数据结构

❌ ​​增加类数量​​:每个集合需配套迭代器,代码复杂度上升

✅ ​​支持多种遍历策略​​:如顺序、逆序、树形遍历(通过不同迭代器实现)

❌ ​​性能开销​​:迭代器对象创建/销毁消耗资源(对简单遍历可能冗余)

✅ ​​简化聚合接口​​:集合只需关注数据管理,遍历逻辑由迭代器处理

❌ ​​不支持随机访问​​:仅顺序遍历,无法高效跳转(如二分查找需额外设计)

✅ ​​开放封闭原则​​:新增集合类型时无需修改客户端代码


🛠️ 四、应用场景

  1. ​复杂数据结构遍历​
    隐藏树、图等结构的遍历细节(如DFS/BFS),客户端统一调用next()

  2. ​统一遍历异构集合​
    对数组、链表、数据库结果集等提供一致的访问接口。

  3. ​需要多种遍历方式​
    如音乐播放列表支持顺序播放、随机播放(不同迭代器实现不同算法)。

  4. ​隔离安全与封装​
    保护集合内部状态(如线程安全集合的迭代器可加锁)。


💡 五、技术实现示例


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框架中遍历窗口内的按钮、文本框等组件。

  • ​游戏开发​​:遍历场景中的实体对象(敌人、道具等)。


💎 总结

迭代器模式通过​​抽象遍历过程​​,解决了集合内部结构与客户端遍历逻辑的强耦合问题,是处理复杂数据结构的核心模式之一。其价值在需支持多种遍历方式或异构集合统一访问时尤为突出,但需权衡其在简单场景中的额外设计成本。