简介
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
提供一种顺序访问聚集/容器对象元素的方法,而又无须暴露聚集内部表象。
迭代器模式(Iterator Pattern) 又称为 游标(Cursor)模式,是对象的行为模式。
迭代器模式 可以顺序地访问一个聚集中的元素,而又不会暴露聚集内部表象。也即 迭代器模式 可以为不同的容器提供一致的遍历行为,而不用关心容器内容元素组成结构。
迭代器模式 本质:抽离聚集对象迭代行为到迭代器中,提供一致访问接口。
主要解决
我们把多个对象聚在一起形成的总体称之为聚集(Aggregate),聚集对象是能够包容一组对象的容器对象。不同的聚集其内部元素的聚合结构可能不同,而 迭代器模式 屏蔽了内部元素获取细节,为外部提供一致的元素访问行为,解耦了元素迭代与集合对象间的耦合,并且通过提供不同的迭代器,可以为同个聚集对象提供不同顺序的元素访问行为,扩展了聚集对象元素迭代功能,符合 开闭原则。
优缺点
优点
- 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的聚集对象;
- 简化聚集对象接口:迭代器模式 将聚集对象本身应该提供的元素迭代接口抽取到了迭代器中,使聚集对象无须关心具体迭代行为;
- 元素迭代功能多样化:每个聚集对象都可以提供一个或多个不同的迭代器,使的同种元素聚合结构可以有不同的迭代行为;
- 解耦迭代与聚集:迭代器模式 封装了具体的迭代算法,迭代算法的变化,不会影响到聚集对象的架构;
缺点
- 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐;
使用场景
- 遍历一个容器对象时;
模式讲解
首先来看下 迭代器模式 的通用 UML 类图:
从 UML 类图中,我们可以看到,迭代器模式 主要包含三种角色:
- 抽象迭代器(Iterator):抽象迭代器负责定义访问和遍历元素的接口;
- 具体迭代器(ConcreteIterator):提供具体的元素遍历行为;
- 抽象容器(Aggregate):负责定义提供具体迭代器的接口;
- 具体容器(ConcreteAggregate):创建具体迭代器;
以下是 迭代器模式 的通用代码:
class Client {
public static void main(String[] args) {
//来一个容器对象
IAggregate<String> aggregate = new ConcreteAggregate<>();
//添加元素
aggregate.add("one");
aggregate.add("two");
aggregate.add("three");
//获取容器对象迭代器
Iterator<String> iterator = aggregate.iterator();
//遍历
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
}
//抽象迭代器
interface Iterator<E> {
E next();
boolean hasNext();
}
//具体迭代器
static class ConcreteIterator<E> implements Iterator<E> {
private List<E> mList;
private int mCursor = 0;
public ConcreteIterator(List<E> list) {
this.mList = list;
}
@Override
public E next() {
return this.mList.get(this.mCursor++);
}
@Override
public boolean hasNext() {
return this.mCursor < this.mList.size();
}
}
//抽象容器
interface IAggregate<E> {
boolean add(E element);
boolean remove(E element);
Iterator<E> iterator();
}
//具体容器
static class ConcreteAggregate<E> implements IAggregate<E> {
private List<E> mList = new ArrayList<>();
@Override
public boolean add(E element) {
return this.mList.add(element);
}
@Override
public boolean remove(E element) {
return this.mList.remove(element);
}
@Override
public Iterator<E> iterator() {
return new ConcreteIterator<E>(this.mList);
}
}
}
通过上面的代码,我们可以更清楚地了解到 迭代器模式 的作用就是将聚集对象的迭代行为抽取到迭代器中,解耦了元素迭代与聚集对象之间的耦合,使得不同的聚集对象对外都能提供一致的迭代行为。
注:认真思考一下 迭代器模式 和 组合模式,其实这两者似乎存在一定的相似性。组合模式 解决的是统一树形结构各层次访问接口,迭代器模式 解决的是统一各聚集对象元素遍历接口。虽然他们的适配场景不同,但核心理念是相通的。