Skip to main content

迭代器模式

概述​

如何操纵任意的对象集合? 如一个列表(List)或者一个集合(Set),又如何提供一种方法来让别人可以访问它的元素,而又不需要暴露它的内部结构? 迭代器模式:使用迭代器模式来提供对聚合对象的统一存取,即提供一个外部的迭代器来对聚合对象进行访问和遍历,而又不需暴露该对象的内部结构。又叫做游标(Cursor)模式。

适用性​

迭代器模式可用来:

  • 访问一个聚合对象的内容而无需暴露它的内部表示。
  • 需要为聚合对象提供多种遍历方式。
  • 为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)

结构​

iterator 结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符合“单一职责原则”。 注意,在迭代器模式中,具体迭代器角色和具体容器角色是耦合在一起的。为了使客户程序从与具体迭代器角色耦合的困境中脱离出来,避免具体迭代器角色的更换给客户程序带来的修改,迭代器模式抽象了具体迭代器角色,使得客户程序更具一般性和重用性。这被称为多态迭代。

模式的组成​

抽象迭代器(Iterator)​

迭代器定义访问和遍历元素的接口。

具体迭代器(ConcreteIterator)​

具体迭代器实现迭代器 Iterator 接口,对该聚合遍历时跟踪当前位置。

抽象聚合类(Aggregate)​

聚合定义创建相应迭代器对象的接口。

具体聚合类(ConcreteAggregate)​

具体聚合实现创建相应迭代器的接口,该操作返回 ConcreteIterator 的一个适当的实例。

迭代器模式的作用​

  • 它支持以不同的方式遍历一个聚合对象:复杂的聚合可用多种方式进行遍历,迭代器模式使得改变遍历算法变得很容易:仅需用一个不同的迭代器的实例代替原先的实例即可
  • 迭代器简化了聚合的接口,有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了
  • 在同一个聚合上可以有多个遍历,每个迭代器保持它自己的遍历状态,因此可以同时进行多个遍历。
  • 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。 迭代器模式的缺点 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

实现​

/**
* 迭代器接口
*/
public interface Iterator<T> {
T next();
boolean hasNext();
}

/**
* 迭代器实现
*/
public class ConcreteIterator<T> implements Iterator<T> {
private List<T> list;
private int index = 0;

public ConcreteIterator(List<T> list) {
this.list = list;
}

@Override
public T next() {
return list.get(index++);
}

@Override
public boolean hasNext() {
return index < list.size();
}
}

/**
* 聚合定义创建相应迭代器对象的接口
*/
public interface Aggregate {
Iterator createIterator();
}

/**
* 具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例
*/
public class ConcreteAggregate<T> implements Aggregate {
private List<T> list = new ArrayList<>();

public Iterator createIterator() {
return new ConcreteIterator(list);
}

public void setList(List<T> list) {
this.list = list;
}
}

public class IteratorTest {
@Test
public void test() {
ConcreteAggregate concreteAggregate = new ConcreteAggregate();
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
list.add("F");
concreteAggregate.setList(list);

Iterator iterator = concreteAggregate.createIterator();
Object object = null;
while (iterator.hasNext()) {
object = iterator.next();
System.out.print(object + " ");
}
}
}

结果​

A B C D E F

迭代器模式与其他相关模式​

组合模式(Composite):迭代器常被应用到像组合模式这样的递归结构上。 工厂方法模式(FactoryMethod):多态迭代器靠 FactoryMethod 来实例化适当的迭代器子类。 备忘录模式(Memento):常与迭代器模式一起使用。迭代器可使用一个 Memento 来捕获一个迭代的状态。迭代器在其内部存储 Memento。

总结与分析​

  • 聚合是一个管理和组织数据对象的数据结构。
  • 聚合对象主要拥有两个职责:一是存储内部数据;二是遍历内部数据。
  • 存储数据是聚合对象最基本的职责。
  • 将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。