Appearance
迭代器模式(Iterator Pattern)笔记
定义
迭代器模式是一种行为设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
英文原文定义:
The Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
核心概念
迭代器模式将遍历集合的责任从集合对象中分离出来,放入迭代器对象中,使得集合接口和实现更加简洁,同时支持多种遍历方式。
主要角色
- Iterator(迭代器接口):定义访问和遍历元素的接口
- ConcreteIterator(具体迭代器):实现迭代器接口,跟踪当前访问位置
- Aggregate(聚合接口):定义创建迭代器对象的接口
- ConcreteAggregate(具体聚合):实现聚合接口,返回具体迭代器实例
优缺点
优点
- 单一职责原则:将遍历算法与集合分离
- 开闭原则:可以新增迭代器类型而不修改集合代码
- 并行遍历:支持多个遍历同时进行
- 统一接口:为不同集合提供统一的遍历方式
- 延迟遍历:支持惰性求值和流式处理
缺点
- 简单集合可能过度设计:对于简单集合使用迭代器可能增加复杂度
- 性能开销:相比直接遍历可能有额外对象创建开销
- 访问限制:某些特殊遍历需求可能难以通过标准迭代器接口实现
解决的问题
迭代器模式主要解决以下经典问题:
- 封装集合内部结构:需要遍历集合但不想暴露其内部表示时
- 支持多种遍历方式:当集合需要支持多种遍历算法时
- 统一遍历接口:为不同集合结构提供一致的遍历接口
- 并行遍历需求:当需要同时进行多个集合遍历时
实现注意事项
- 迭代器所有权:明确谁负责迭代器的生命周期管理(集合还是客户端)
- 遍历算法复杂度:确保迭代器的next()和hasNext()操作保持O(1)时间复杂度
- 并发修改检测:实现fail-fast机制检测遍历过程中的集合修改
- 内部迭代器:考虑提供内部迭代器简化客户端代码
- 资源清理:迭代器可能持有资源,需要实现AutoCloseable或明确清理机制
实现变体
外部迭代器(主动迭代器):
- 客户端控制迭代过程
- 显式调用next()前进迭代
- Java的Iterator是典型实现
内部迭代器(被动迭代器):
- 迭代器控制整个迭代过程
- 接受回调函数处理每个元素
- Java的forEach是典型实现
惰性迭代器:
- 按需计算/获取元素
- 支持无限序列
- Java的Stream是典型实现
双向迭代器:
- 支持向前和向后遍历
- 额外提供previous()等方法
- ListIterator是典型实现
与其他模式的关系
相似模式区分
访问者模式:
- 迭代器:专注于遍历集合元素
- 访问者:专注于对元素执行操作
组合模式:
- 迭代器:用于遍历组合结构
- 组合:描述部分-整体层次结构
工厂方法模式:
- 迭代器常通过工厂方法创建
- 工厂方法定义创建接口,具体聚合决定实现
常见搭配组合
- 迭代器 + 组合:用于遍历组合结构
- 迭代器 + 工厂方法:通过工厂方法创建迭代器
- 迭代器 + 备忘录:实现迭代状态的保存和恢复
- 迭代器 + 访问者:遍历时应用访问者操作
典型应用场景
- 集合框架(Java Collection Framework)
- 树形结构遍历(文件系统、DOM树)
- 数据库结果集遍历
- 分页查询实现
- 延迟加载的数据流处理
- 图算法中的邻接节点遍历
代码示例(外部迭代器实现)
java
// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
}
// 聚合接口
interface Aggregate<T> {
Iterator<T> iterator();
}
// 具体聚合
class BookShelf implements Aggregate<Book> {
private Book[] books;
private int last = 0;
public BookShelf(int size) {
this.books = new Book[size];
}
public Book getBookAt(int index) {
return books[index];
}
public void appendBook(Book book) {
this.books[last++] = book;
}
public int getLength() {
return last;
}
@Override
public Iterator<Book> iterator() {
return new BookShelfIterator(this);
}
}
// 具体迭代器
class BookShelfIterator implements Iterator<Book> {
private BookShelf bookShelf;
private int index = 0;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return index < bookShelf.getLength();
}
@Override
public Book next() {
return bookShelf.getBookAt(index++);
}
}
// 客户端代码
BookShelf shelf = new BookShelf(4);
shelf.appendBook(new Book("Design Patterns"));
shelf.appendBook(new Book("Clean Code"));
Iterator<Book> it = shelf.iterator();
while (it.hasNext()) {
System.out.println(it.next().getName());
}