一、定义
迭代器(Iterator)模式又叫作游标(Cursor)模式,是一种对象的行为模式。提供一种方法顺序访问一个聚合(指一组对象的组合结构,如:Java中的集合、数组等)对象中各个元素,而又不需暴露该对象的内部表示。迭代器模式的本质:控制访问聚合对象中的元素。其设计意图:无须暴露聚合对象的内部实现,就能够访问到聚合对象中的各个元素。
二、角色
抽象迭代器(Iterator)角色: 一般定义为接口,用来定义访问和遍历元素的接口。
具体迭代器(ConcreteIterator)角色: 实现对聚合对象的遍历,并跟踪遍历时的当前位置。
抽象聚合(Aggregate)角色: 定义创建相应迭代器对象的接口。
具体聚合(ConcreteAggregate)角色: 实现创建相应的迭代器对象。
三、示例
① Iterator
接口。
public interface Iterator {
/**
* 移动到聚合对象中下一个元素
*/
void next();
/**
* 判断是否已经移动到聚合对象的最后一个元素
*/
boolean isDone();
/**
* 获取迭代的当前元素
*/
Object currentItem();
}
② ConcreteIterator
实现类。
public class ConcreteIterator implements Iterator {
private ConcreteAggregate concreteAggregate;
private int index = 0;
ConcreteIterator(ConcreteAggregate concreteAggregate) {
this.concreteAggregate = concreteAggregate;
}
@Override
public void next() {
if (index < this.concreteAggregate.size()) {
index++;
}
}
@Override
public boolean isDone() {
if (index == this.concreteAggregate.size()) {
return true;
}
return false;
}
@Override
public Object currentItem() {
return this.concreteAggregate.get(index);
}
}
③ Aggregate
抽象类。
public abstract class Aggregate {
/**
* 工厂方法,创建相应的迭代器对象的接口
*/
public abstract Iterator createIterator();
}
④ ConcreteAggregate
实现类。
public class ConcreteAggregate extends Aggregate {
private String[] value;
ConcreteAggregate(String[] value) {
this.value = value;
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
public int size() {
return this.value.length;
}
public Object get(int index) {
Object retObj = null;
if (index < value.length) {
retObj = value[index];
}
return retObj;
}
}
⑤ Test
测试类。
public class Test {
public static void main(String[] args) {
String[] names = { "张三", "李四", "王五" };
// 创建聚合对象
ConcreteAggregate aggregate = new ConcreteAggregate(names);
Iterator iterator = aggregate.createIterator();
while (!iterator.isDone()){
System.out.println(iterator.currentItem());
iterator.next();
}
}
}
从以上示例可以看出,迭代器模式为客户端提供了一个统一访问聚合对象的接口,通过这个接口就可以顺序地访问聚合对象的元素。对于客户端而言,只是面向这个接口在访问,根本不知道聚合对象内部的实现细节(聚合对象可以是集合,也可以是数组,客户端无从得知)。
使用迭代器模式,还可以实现很多更加丰富的功能。比如:
- 以不同的方式遍历聚合对象,比如向前、向后等;
- 对同一个聚合同时进行多个遍历;
- 以不同的遍历策略来遍历聚合,比如是否需要过滤等;
- 多态迭代,含义是:为不同的聚合结构提供统一的迭代接口,也就是说通过一个迭代接口可以访问不同的聚合结构。(多态迭代可能会带来类型安全的问题,可以考虑使用泛型)。
四、迭代器模式的适用性
在以下条件下可以考虑使用迭代器模式:
- 如果你希望为遍历不同的聚合对象提供一个统一的接口,可以使用迭代器模式;
- 如果你希望有多种遍历方式可以访问聚合对象,可以使用迭代器模式;
- 如果你希望提供访问一个聚合对象的内容,但是又不想暴露它的内部表示的时候,可以使用迭代器模式来提供迭代器接口,从而让客户端只是通过迭代器的接口来访问聚合对象,而无须关心聚合对象的内部实现。
五、迭代器模式的优缺点
优点:
- 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计;
- 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求;
- 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
缺点:
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性;
- 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如JDK内置迭代器Iterator就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类ListIterator等来实现,而ListIterator迭代器无法用于操作Set类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。