迭代器模式
迭代器模式(Iterator Pattern):统一访问集合元素的方式
迭代器模式是行为型设计模式的一种,核心思想是提供一种统一的方法顺序访问容器对象(如集合、数组)中的各个元素,而不暴露容器的内部结构。这种模式就像 “遥控器”—— 无论电视机的内部构造如何,用户只需通过遥控器的按键(迭代器方法)就能逐频道切换(遍历元素),无需了解电视的内部细节。
迭代器模式的核心结构

迭代器模式通过四个核心角色实现对容器元素的统一遍历,职责明确且解耦了容器与遍历逻辑:
迭代器接口(Iterator)
- 定义遍历容器元素的标准接口,通常包含以下方法:
hasNext():判断是否还有下一个元素。next():返回当前元素,并移动到下一个位置。- (可选)
remove():移除当前元素(视容器支持情况)。
- 示例:
java.util.Iterator(Java 集合框架的迭代器接口)。
具体迭代器(ConcreteIterator)
- 实现迭代器接口,封装具体的遍历逻辑,记录当前遍历位置,与特定容器绑定。
- 示例:
ArrayList的内部迭代器(遍历数组)、LinkedList的内部迭代器(遍历链表)。
容器接口(Collection/Aggregate)
- 定义容器的核心接口,声明创建迭代器的方法(
iterator()),是所有容器的抽象父类。 - 示例:
java.util.Collection(Java 集合的根接口)。
具体容器(ConcreteCollection)
- 实现容器接口,存储元素并提供创建对应迭代器的方法,负责管理元素的增删改查。
- 示例:
ArrayList(数组容器)、HashSet(哈希表容器)。
代码实现示例
以 “自定义列表容器” 为例,展示迭代器模式的实现:自定义MyList容器,通过迭代器遍历元素,不暴露内部存储结构(如数组)。
1. 迭代器接口与具体迭代器
// 1. 迭代器接口
public interface MyIterator<E> {
boolean hasNext(); // 是否有下一个元素
E next(); // 获取下一个元素
}
// 2. 具体迭代器(与MyArrayList绑定)
public class MyArrayListIterator<E> implements MyIterator<E> {
private MyArrayList<E> list; // 关联的容器
private int index = 0; // 当前遍历索引
public MyArrayListIterator(MyArrayList<E> list) {
this.list = list;
}
public boolean hasNext() {
return index < list.size(); // 索引未超出容器大小则有下一个元素
}
public E next() {
if (!hasNext()) {
throw new NoSuchElementException("没有更多元素");
}
return list.get(index++); // 返回当前元素并移动索引
}
}
2. 容器接口与具体容器
// 3. 容器接口
public interface MyCollection<E> {
void add(E element); // 添加元素
E get(int index); // 获取指定位置元素
int size(); // 获取元素数量
MyIterator<E> iterator(); // 创建迭代器
}
// 4. 具体容器(基于数组实现)
public class MyArrayList<E> implements MyCollection<E> {
private Object[] elements; // 内部存储结构(数组,不暴露给外部)
private int size = 0; // 元素数量
public MyArrayList(int capacity) {
elements = new Object[capacity];
}
public void add(E element) {
if (size < elements.length) {
elements[size++] = element;
} else {
throw new IndexOutOfBoundsException("容器已满");
}
}
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界");
}
return (E) elements[index];
}
public int size() {
return size;
}
public MyIterator<E> iterator() {
// 返回与当前容器绑定的迭代器
return new MyArrayListIterator<>(this);
}
}
3. 客户端使用
public class IteratorDemo {
public static void main(String[] args) {
// 创建容器并添加元素
MyCollection<String> list = new MyArrayList<>(5);
list.add("元素1");
list.add("元素2");
list.add("元素3");
// 获取迭代器并遍历
MyIterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
}
}
输出结果
元素1
元素2
元素3
迭代器模式的核心优势
- 统一遍历接口
无论容器内部结构是数组、链表还是哈希表,客户端都可通过相同的hasNext()和next()方法遍历,无需关心容器的具体实现(如ArrayList和LinkedList的遍历代码完全一致)。 - 隐藏容器内部结构
客户端仅通过迭代器访问元素,无需知道容器是用数组还是链表存储的,降低了客户端与容器的耦合度,保护了容器的封装性。 - 支持多种遍历方式
一个容器可提供多个迭代器实现不同的遍历逻辑(如正向遍历、反向遍历、过滤遍历),客户端可根据需求选择。 - 简化容器接口
容器无需暴露大量遍历相关的方法(如get(int index)可能仅用于内部),只需提供iterator()方法即可。
适用场景
- 需要统一遍历不同容器
当系统中存在多种容器(如数组、集合、树),且希望用相同的代码遍历它们时(如 Java 集合框架的for-each循环)。 - 不希望暴露容器内部结构
容器的内部实现(如哈希表的桶数组、链表的节点)属于私有细节,不应暴露给客户端,迭代器是安全的访问方式。 - 需要多种遍历方式
如对列表需要正向遍历、反向遍历或按条件筛选遍历,可通过不同的迭代器实现。 - 迭代逻辑复杂或易变
将遍历逻辑封装在迭代器中,便于修改或扩展(如优化遍历性能),不影响容器本身。
优缺点分析
优点
- 遍历接口统一:客户端代码更简洁,无需针对不同容器编写不同遍历逻辑。
- 封装性好:容器内部结构对客户端透明,降低耦合度。
- 扩展性强:新增容器或迭代方式时,只需实现对应的容器和迭代器接口,不影响现有代码。
缺点
- 额外的类开销:每个容器需对应一个或多个迭代器类,增加了系统的类数量。
- 迭代器与容器绑定:迭代器依赖于特定容器,更换容器可能需要更换迭代器(但客户端无需修改遍历代码)。
经典应用:Java 集合框架的迭代器
Java 的java.util.Iterator是迭代器模式的典范,几乎所有集合类(ArrayList、HashMap、TreeSet等)都实现了Iterator接口,使遍历代码高度统一:
// 遍历ArrayList
List<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
Iterator<String> it1 = arrayList.iterator();
while (it1.hasNext()) {
System.out.println(it1.next());
}
// 遍历HashSet(代码完全相同)
Set<String> hashSet = new HashSet<>();
hashSet.add("X");
hashSet.add("Y");
Iterator<String> it2 = hashSet.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
}
甚至可通过增强 for 循环(for-each)简化遍历,其底层仍依赖迭代器:
for (String s : arrayList) {
System.out.println(s);
}
总结
迭代器模式通过分离容器与遍历逻辑,提供了一种统一、安全的元素访问方式,是处理集合类数据的核心模式。其核心价值在于 “接口统一” 和 “封装内部结构”,使客户端能专注于元素的使用而非容器的实现