基本概念

迭代器模式:一种行为型设计模式,它提供一种顺序访问集合对象元素的方法,而无需暴露集合的内部表示。通过将遍历逻辑与集合本身解耦,使得不同遍历方式可以独立变化。

核心结构

  1. 迭代器接口(Iterator):定义遍历元素的方法(如hasNext()next()remove())。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,维护遍历的当前位置。
  3. 聚合接口(Aggregate):定义创建迭代器的方法(如createIterator())。
  4. 具体聚合(Concrete Aggregate):实现聚合接口,返回具体迭代器实例。

示例说明

场景:自定义数组的迭代器

  1. 定义迭代器接口
1
2
3
4
5
6
7
8

// 迭代器接口
interface Iterator<T> {
boolean hasNext(); // 是否有下一个元素
T next(); // 获取下一个元素
void remove(); // 删除当前元素(可选)
}

  1. 定义聚合接口
1
2
3
4
5

// 聚合接口
interface Aggregate<T> {
Iterator<T> createIterator(); // 创建迭代器
}
  1. 自定义实现一个数据实现聚合接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

class MyArray<T> implements Aggregate<T> {
private T[] elements;
private int size;

public MyArray(int capacity) {
elements = (T[]) new Object[capacity];
size = 0;
}

// 向数组添加元素
public void add(T element) {
if (size < elements.length) {
elements[size++] = element;
}
}

// 获取数组长度
public int getSize() {
return size;
}

// 获取指定位置的元素
public T get(int index) {
if (index >= 0 && index < size) {
return elements[index];
}
throw new IndexOutOfBoundsException();
}

// 创建并返回具体迭代器
@Override
public Iterator<T> createIterator() {
return new ArrayIterator<>(this);
}

// 具体迭代器:数组迭代器
private class ArrayIterator<T> implements Iterator<T> {
private MyArray<T> array;
private int currentIndex = 0;

public ArrayIterator(MyArray<T> array) {
this.array = array;
}

@Override
public boolean hasNext() {
return currentIndex < array.getSize();
}

@Override
public T next() {
if (hasNext()) {
return array.get(currentIndex++);
}
throw new IllegalStateException("没有更多元素");
}

@Override
public void remove() {
if (currentIndex > 0) {
// 简化实现,实际需处理元素移动
array.elements[currentIndex - 1] = null;
array.size--;
currentIndex--;
}
}
}
}
  1. 测试验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

public class Test {
public static void main(String[] args) {
// 创建聚合对象
MyArray<String> names = new MyArray<>(5);
names.add("张三");
names.add("李四");
names.add("王五");

// 获取迭代器并遍历
Iterator<String> iterator = names.createIterator();
System.out.println("使用迭代器遍历:");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}

// 另一种遍历方式(内部迭代)
System.out.println("\n使用for-each遍历(Java内置迭代器支持):");
for (String name : names) { // 需MyArray实现Java的Iterable接口
System.out.println(name);
}
}
}

实现这个模式,给了一种遍历元素的而不知道事务在底层如何表达的方式。迭代器模式拿走了遍历元素的责任,把它交给迭代器对象而不是聚合对象。这不仅让聚合的接口和实现更加简单,它还从聚合移除了遍历的责任,让聚合专注于管理对象集合。

专门设计一个迭代器类,负责遍历集合的操作,这就涉及一个新的设计原则,单一职责原则:一个类应该只有一个变化的原因。这个原则指引我们,只把一个责任分配给一个类而且仅一个类

类图如下:

迭代器模式

总结

优点

  • 解耦遍历与集合:客户端无需知道集合内部结构,仅通过迭代器操作元素。
  • 支持多种遍历方式:可针对同一集合创建不同迭代器(如正序、倒序、过滤遍历)。
  • 符合单一职责:集合类专注于数据存储,迭代器专注于遍历逻辑。
  • 简化集合接口:客户端无需暴露集合的索引或指针,提高安全性。

缺点

  • 类数量增加:引入迭代器和聚合接口,可能导致类爆炸(但现代语言常内置支持)。
  • 对内置支持的依赖:若语言原生支持迭代器(如Java的Iterator),自定义迭代器成本降低。

使用场景

  • 需要统一遍历接口:不同集合(数组、链表、树)提供一致的遍历方式。

  • 集合内部复杂:不想暴露集合的存储结构(如链表的节点指针)。

  • 支持多种遍历逻辑:如文件系统遍历(按名称、按时间、按类型)。

  • 惰性加载场景:迭代器可按需加载元素(如数据库查询的分页遍历)。

  • 并行遍历需求:多个迭代器可同时遍历同一集合(需考虑线程安全)。

    迭代器模式的核心是“分离遍历逻辑与数据存储”,就像超市的购物车——无论货架如何摆放(集合内部结构),顾客(客户端)只需通过购物车的把手(迭代器)按顺序挑选商品。这种模式在Java集合框架、文件IO、数据库查询等场景中使用较多。

    通过迭代器,系统可更灵活地支持不同遍历策略,同时保证集合内部数据的封装性。