初探迭代器模式

代码链接

koonchen/design-patterns/iterator

要点

提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。

一个聚合对象,如列表我们需要一个方法来让别人可以访问它的元素,关键在于列表的访问和遍历从中分离出一个迭代器对象。

下面是一个列表和一个列表迭代器,他们是耦合在一起的:

cover

客户对象必须知道遍历的是一个列表而不是其他聚合结构,最好有一种方法能使得不改变客户代码即改变该聚合类。

cover

现在我们分离操作列表的公共接口,以及公共迭代接口,令迭代机制和聚合类无关。

迭代器模式的适用性:

  • 访问一个聚合对象的内容而无需暴露它的内部表示
  • 支持对聚合对象的多种遍历
  • 为遍历不同的聚合结构提供一个统一的接口

迭代器模式的参与者:

  • Iterator — 迭代器定义访问和遍历元素的接口
  • ConcreteIterator — 具体迭代器实现迭代器接口
  • Aggregate — 聚合定义创建相应迭代器对象的接口
  • ConcreteAggregate — 具体聚合实现创建相应迭代器的接口

现在迭代器模式的结构已经显而易见了:

cover

迭代器有三个重要的作用:

  • 它支持以不同的方式遍历一个聚合:复杂的聚合可用多种方式进行遍历。
  • 迭代器简化了聚合的接口:有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了。
  • 在同一个聚合上可以有多个遍历:每个迭代器保持它自己的遍历状态。

实现

实现迭代器模式常常需要一些权衡:

  • 谁控制该迭代:一个基本的问题是决定由哪一方来控制该迭代,是迭代器是还使用该迭代器的客户。客户决定称为外部迭代器,由该迭代器决定称为内部迭代器。
  • 谁定义遍历算法:迭代器不是唯一可定义遍历算法的地方。聚合本身也可以遍历算法,并在遍历的过程中用迭代器来存储当前迭代的状态。
  • 迭代器健壮程度如何:在遍历一个聚合的同事更改这个聚合是危险的。
  • 附加的迭代器操作:迭代器的最小接口由各种操作组成其他一些操作可能也很有用。
  • 迭代器可有特权访问:迭代器可被看为创建它的聚合的一个扩展。
  • 用于复合对象的迭代器:在组合模式中的那些递归聚合结构上,外部迭代器可能难以实现,因为该结构中不同对象处于嵌套聚合的多个不同层次,因此一个外部迭代器为跟踪当前的对象必须存储一条纵贯该组合的路径。
  • 空迭代器:一个空迭代器是一个退化的迭代器,它有助于边界处理。

Java 实现

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.util.ArrayList;
import java.util.List;

interface Aggregate {
ConcreteIteraor createIterator();
// add
List getList();
}

interface Iterator<T> {
T first();
T next();
boolean isDone();
T currentItem();
}

class ConcreteIteraor implements Iterator<Integer> {

private Aggregate aggregate;
private int idx;


public ConcreteIteraor(Aggregate aggregate) {
this.aggregate = aggregate;
this.idx = -1;
}

@Override
public Integer first() {
List list = this.aggregate.getList();
return (Integer) list.get(0);
}

@Override
public Integer next() {
List list = this.aggregate.getList();
return (Integer) list.get(++idx);
}

@Override
public boolean isDone() {
System.out.println("the method has been used");
return true;
}

@Override
public Integer currentItem() {
List list = this.aggregate.getList();
return (Integer) list.get(idx);
}
}

// 聚合类
class ConcreteAggregate implements Aggregate {

private List<Integer> list;

public ConcreteAggregate() {
list = new ArrayList();
list.add(3);
list.add(10);
list.add(1);
}

@Override
public ConcreteIteraor createIterator() {
return new ConcreteIteraor(this);
}

@Override
public List<Integer> getList() {
return this.list;
}
}

public class IteratorClient {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate();
Iterator iterator = aggregate.createIterator();
Integer item = (Integer) iterator.next();
System.out.println(item);
}
}

相关模式:

Composite: 迭代器通常被应用到复合这样的递归结构上

Factory Method: 多态迭代器靠 Factory Method 来实例化适当的迭代器子类

Memento: 常与迭代器模式一起使用