迭代器模式的核心是解耦遍历逻辑与数据结构,通过聚合接口(createIterator)、具体聚合类、迭代器接口(hasNext/next)和具体迭代器四角色协作,使客户端以统一方式遍历不同容器;其本质是线性推进的状态机,严禁在next()中使用递归,而应将递归逻辑(如树遍历)平展为栈或队列等显式迭代结构封装于具体迭代器内部。

明确角色分工:四个关键组件
一个标准迭代器模式包含四类角色,缺一不可:
-
聚合接口(Aggregate):只声明一个方法
createIterator(),告诉外界“我能被遍历”; - 具体聚合类(如 BookShelf、ArrayList):真正存数据的地方,负责 new 出对应的迭代器;
-
迭代器接口(Iterator):定义通用操作,至少含
hasNext()和next(); - 具体迭代器(如 BookShelfIterator、ArrayListIterator):封装遍历细节,比如用 index 走数组、用指针走链表、用栈模拟树的 DFS。
手写一个可用的迭代器(Java 示例)
不依赖 JDK 的 Iterator,自己实现一个书架遍历器,便于理解控制流:
先定义聚合接口:
interface Aggregate<T> {
Iterator<T> createIterator();
}
再写具体聚合类:
class BookShelf implements Aggregate<String> {
private final List<String> books = new ArrayList<>();
public void add(String title) { books.add(title); }
@Override
public Iterator<String> createIterator() {
return new BookShelfIterator(books);
}
}
最后是具体迭代器(状态全由它维护):
class BookShelfIterator implements Iterator<String> {
private final List<String> list;
private int cursor = 0;
BookShelfIterator(List<String> list) { this.list = list; }
@Override public boolean hasNext() { return cursor < list.size(); }
@Override public String next() { return list.get(cursor++); }
}
客户端只需面向接口写一次循环,换聚合类也不改代码:
Aggregate<String> shelf = new BookShelf();
shelf.add("Design Patterns");
shelf.add("Clean Code");
Iterator<String> it = shelf.createIterator();
while (it.hasNext()) {
System.out.println(it.next()); // 输出两本书名
}
为什么要避免在迭代器里写递归?
迭代器本质是**线性推进的状态机**,每次调用 next() 只做一步移动+返回当前值。如果在 next() 里用递归(比如遍历树时自己调自己),会带来三个问题:
- 栈深度不可控,容易 StackOverflow;
- 无法暂停/恢复遍历(迭代器需支持中途 break 或多次调用);
- 破坏了“单次调用只推进一次”的契约,让使用者难以预测行为。
正确做法是把递归逻辑平展为迭代:树的中序遍历就用显式栈模拟;DFS 就用 Stack,BFS 就用 Queue —— 这些都封装在具体迭代器内部,对外仍是干净的 hasNext()/next()。
现代语言中的“隐形迭代器”
你每天都在用,只是没察觉:
- Java 的
for (String s : list)底层调用list.iterator(); - C++ 的
std::vector::begin()/end()返回的是符合 STL 迭代器规范的对象; - Python 的
__iter__()和__next__()就是迭代器协议。
它们共同点是:把索引管理、越界判断、元素提取全部收进一个对象,外部只管“取下一个”,不用操心下标越没越界、指针空不空、树走到哪一层。

















