迭代器模式
提供一种方法顺序访问到一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
类结构图
Aggregate
聚集抽象类。
ConcreteAggregate
具体的聚集类,继承 Aggregate。
Iterator
迭代抽象类,用于定义得到开始对象、得到下一个对象、判断是否到结尾、当前对象等抽象方法,统一接口。
ConcreteIterator
具体迭代器类,继承 Iterator,实现开始、下一个、是否结尾对象等方法。
为什么会出现这种设计模式?
例如我们所学的集合类 ArrayList、LinkedList、HashSet 由于内部数据结构的不一致所以无法同一种方式遍历,为了给客户端提供统一的遍历方式所以迭代器模式出现了。
代码示例
public interface Aggregate<T> {
Iterator<T> iterator();
}
public interface Iterator<T> {
boolean hashNext();
T next();
}
public class ConcreteAggregate<T> implements Aggregate {
private List<T> list = new ArrayList<>();
public void add(T t) {
list.add(t);
}
@Override
public Iterator iterator() {
return new ConcreteAggregateIterator();
}
private class ConcreteAggregateIterator implements Iterator<T> {
private int currentIndex;
@Override
public boolean hashNext() {
return this.currentIndex < ConcreteAggregate.this.list.size();
}
@Override
public T next() {
T t = null;
if (this.currentIndex < ConcreteAggregate.this.list.size()) {
t = ConcreteAggregate.this.list.get(this.currentIndex);
this.currentIndex++;
}
return t;
}
}
}
客户端示例
public class Client {
public static void main(String[] args) {
ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
aggregate.add("1");
aggregate.add("2");
aggregate.add("3");
for (Iterator iterator = aggregate.iterator(); iterator.hashNext(); ) {
System.out.println(iterator.next());
}
}
}
运行结果
1
2
3
Process finished with exit code 0
这次是采用的内部类实现的,并没有使用类结构图里的实现的。这样做的想法是内部类是为了完全杜绝客户端对迭代器实现类的依赖。
使用场景
要达到某一个目的,根据具体的实际情况,选择合适的方法。适合于实现某一个功能有多种方案可以选择的情景。
优点
分离了集合对象的遍历行为,抽象出一个迭代器类来负责,弱化了容器类与遍历算法之间的关系。
缺点
- 仅适用于访问容器。
- 对于比较简单的遍历(数组或者有序列表),使用迭代器方式遍历较为繁琐而且遍历效率不高,使用迭代器的方式比较适合那些底层以链表形式实现的集合。