Demo 地址: https://github.com/ooblee/HelloDesignPattern
1. 定义
迭代器模式(Iterator Pattern):提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。
聚合对象两大重要职责:
- 存储数据。
- 遍历数据。
可以使用迭代器来进行数据的遍历。迭代器提供统一的接口来访问对象。
Java 的集合基本都实现了迭代器。
2. 设计
主要角色:
- 抽象迭代器(Iterator),定义访问和遍历聚合对象的方法。
- 具体迭代器(Concrete Iterator),实现抽象迭代器,完成聚合对象的遍历。内部会有游标来记录当前的元素位置。
- 抽象聚合类(Aggregate),定义创建抽象迭代器的方法。进行聚合对象元素的存储和管理。
- 具体聚合类(Concrete Aggregate),实现抽象迭代器。
类图:
3. 应用
使用场景:
- 隐藏内部实现,使用迭代器进行遍历,可以不用关心聚合对象的内部组织关系和数据存储方式。
- 多种遍历方式,可以增加不同的迭代器,来达到一个聚合对象的多种迭代方式。
- 统一接口,不同的聚合对象,有统一的方式进行迭代,简化遍历。
现实应用中,我们直接使用各个语言自己实现的迭代器就好了。不需要重复造轮子。
3.1. java.util.Iterator
JDK1.8 的抽象迭代器 Iterator 定义如下:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
各个方法的作用:
- hasNext,是否有下一个元素
- next,返回下一个元素
- remove,删除元素
- forEachRemaining,使用 Lambda 的风格,函数式调用,进行元素的迭代处理。
使用方式:
public class TestIterator {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("hello.");
list.add("hi.");
list.add("你好.");
list.add("hola.");
// 普通方式迭代
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String content = iterator.next();
System.out.println(content);
}
// Lambada 风格
iterator = list.iterator();
iterator.forEachRemaining(System.out::println);
}
}
4. 特点
4.1. 优势
- 易修改,如果需要更换遍历算法,更换相应的具体迭代器,对客户端的代码不用修改。
- 易扩展,可以很方便地新增聚合对象和迭代器。
- 简化聚合对象,聚合对象不需要单独提供数据遍历的方法。
4.2. 缺点
- 复杂性增加,每种聚合对象需要单独实现迭代器,会导致迭代器数量膨胀。
- 设计复杂,迭代器的设计需要考虑到未来的变化,尽可能地思考全面。否则修改抽象实现会影响到所有实现类。