迭代器模式
# 介绍
迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。
- 定义:我们可以用相同的方式处理集合,无论它是列表还是数组,它都提供了一种迭代其元素而不用暴露其内部结构的机制,更重要的是,不同的类型的集合都可以使用相同的统一机制,这种机制则被称为 迭代器模式。
- 目的:提供一种顺序遍历聚合对象元素,而不暴露其内部实现的方法
# 结构
迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。
客户端 (Client) 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。
客户端通常不会自行创建迭代器, 而是会从集合中获取。 但在特定情况下, 客户端可以直接创建一个迭代器 (例如当客户端需要自定义特殊迭代器时)。
# 案例代码
public interface Aggregate {
// 添加元素
void add(Object object);
// 移除元素
void remove(Object object);
// 迭代器
Iterator iterator();
}
public interface Iterator<E> {
// 判断容器是否有值
boolean hasNext();
// 把游标执向下一个指针
void next();
// 当前遍历的数据
E currentItem();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ConcreteAggregate implements Aggregate {
private ArrayList arrayList = new ArrayList();
@Override
public void add(Object object) {
this.arrayList.add(object);
}
@Override
public void remove(Object object) {
this.arrayList.remove(object);
}
@Override
public Iterator iterator() {
return new ConcreteIterator(this.arrayList);
}
}
public class ConcreteIterator<E> implements Iterator<E> {
private int cursor; // 游标
private ArrayList arrayList;
public ConcreteIterator(ArrayList arrayList) {
this.cursor = 0;
this.arrayList = arrayList;
}
@Override
public boolean hasNext() {
if (this.cursor == this.arrayList.size()) {
return false;
}
return true;
}
@Override
public void next() {
cursor++;
System.out.println(cursor + " cursor");
}
@Override
public E currentItem() {
if (cursor >= arrayList.size()) {
throw new NoSuchElementException();
}
E e = (E) arrayList.get(cursor);
this.next();
return e;
}
}
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
最后就是实现具体的迭代器了, 在currentItem里面根据遍历的游标,获取数组里面的值
# 优缺点
单一职责原则。 通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理。
开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。
你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态。
相似的, 你可以暂停遍历并在需要时继续。
如果你的程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。
对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。