迭代器模式的核心是分离“谁来负责遍历”的责任,将遍历逻辑从集合中剥离交由独立迭代器对象处理;它通过Iterator、ConcreteIterator、Aggregate、ConcreteAggregate四个角色协作实现,支持多种遍历策略且不暴露集合内部结构。

迭代器模式的核心不是“怎么遍历”,而是“谁来负责遍历”——它把“知道怎么走”的责任,从集合本身剥离出来,交给独立的迭代器对象。这种分离让集合专注存数据,迭代器专注走逻辑,两者互不干扰。
为什么必须分离遍历和结构?
直接在集合类里写 for 循环或 while 遍历,会带来三个硬伤:
- 暴露内部实现:比如用数组就暴露索引,用链表就暴露 next 指针,客户端一不小心就依赖了这些细节
- 遍历方式被锁死:想加个逆序遍历?得改集合类;想支持跳过空元素?又得动原有代码
- 多结构难统一:数组、树、图的遍历逻辑天差地别,但客户端不该为每种结构写一套访问逻辑
四个角色各司其职,缺一不可
迭代器模式不是靠“一个接口”撑起来的,而是靠四层协作落地:
- Iterator(抽象迭代器):只定义协议,比如 hasNext()、next()、reset(),不关心怎么实现
- ConcreteIterator(具体迭代器):持有对具体集合的引用,知道如何在链表里找下一个节点,或在树里做中序推进
- Aggregate(抽象聚合):只声明 createIterator() 方法,不指定返回哪种迭代器
- ConcreteAggregate(具体集合):真正创建 ConcreteIterator 实例,比如 ArrayList 返回 ArrayIterator,BinaryTree 返回 InorderIterator
语言层面的体现,远比手写更常见
你每天都在用迭代器模式,只是没意识到:
- Python 的 for item in list: 底层调用 iter(list) 和 next(),list 类实现了 __iter__ 和 __next__
- Java 的 for (String s : list) 编译后就是调 Iterator.hasNext() + Iterator.next()
- ES6 的 for...of 要求对象有 Symbol.iterator 方法,Map、Set、Array 原生支持,普通对象需手动实现
真正考验设计的,是边界与扩展
一个健壮的迭代器实现,要处理好三类问题:
- 状态一致性:多个迭代器同时遍历同一集合时,不能互相干扰(比如 Java 的 fail-fast 机制)
- 遍历中途修改:是否允许 remove()?如果允许,是安全删除还是抛异常?这由 ConcreteIterator 决定
- 多种遍历策略:同一棵树,可提供前序、中序、后序、层序四种 ConcreteIterator,客户端按需选用,集合类完全无感










