提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。迭代器模式的关键思想是将对聚集对象的访问和遍历从队列对象中分离出来,并放入一个迭代器对象中,迭代器类定义了一个访问该聚集对象的接口。另外,迭代器和聚集对象是聚合在一起的,而且客户对象必须知道遍历的是哪个具体的聚集对象,以及它的结构是什么,这可以通过多态来实现。使用迭代器模式时分为两种迭代形式:外部迭代,由客户来控制迭代;内部迭代,由迭代器控制迭代。使用外部迭代是比较灵活的,但是需要外部客户主动控制迭代的过程。
public interface Iterator<E> {
public void first();
public void next();
public boolean isDone();
public E currentItem();
}
public interface Aggregate<E> {
public void setValue(int index, E value);
public Iterator<E> createIterator();
}
public class ConcreteAggregate<E> implements Aggregate<E> {
private E list[] = null;
private int size = 0;
@SuppressWarnings("unchecked")
public ConcreteAggregate(int size) {
list = (E[]) new Object[size];
this.size = size;
}
public void setValue(int index, E value){
if(index < size){
list[index] = value;
}
}
public String toString(){
return Arrays.toString(list);
}
@Override
public Iterator<E> createIterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int now = 0;
@Override
public void first() {
now = 0;
}
@Override
public void next() {
now++;
}
@Override
public boolean isDone() {
return now >= size;
}
@Override
public E currentItem() {
return list[now];
}
}
}
public class Client {
@Test
public void test(){
Aggregate<String> list = new ConcreteAggregate<>(5);
list.setValue(0, "a");
list.setValue(1, "b");
list.setValue(3, "c");
list.setValue(4, "d");
Iterator<String> itr = list.createIterator();
while(!itr.isDone()){
System.out.print(itr.currentItem()+", ");
itr.next();
}
System.out.println();
System.out.println(list);
}
}
这里使用ConcreteAggregate来模拟了一个List,它的内部有一个对象数组,并且可以通过返回迭代器来遍历整个对象数组,迭代器内部会保存当前的遍历状态,因此这是一个内部迭代。ConcreteAggregate继承自Aggregate,它包含了添加元素和生成迭代器的接口。Itetator是迭代器的接口,它提供了基本迭代要求,在ConcreteAggregate中实现了这个接口,并返回这个实现类的实例用于迭代。使用内部类可以让迭代器对象方便的访问ConcreteAggregate类中的状态。
最后值得注意的是,在Java中一般的迭代器在遍历的过程中是不允许使用迭代器提供的remove方法之外的方法删除元素的(如ArrayList的remove(index)方法,如果使用迭代器迭代时调用了remove(index)会导致IllegalStateException异常)。