【引入】
对于容器对象的访问,必然会涉及遍历算法。如果将遍历封装到容器中,对于容器来说,承担的功能有点多。如果让用户自己实现,那又必须暴露容器的内部实现。所以使用迭代器模式,在客户访问类与容器体之间插入一个第三者-迭代器。
一、迭代器模式
迭代器模式(行为设计模式):提供一种方法顺序访问一个容器对象中的各个元素,而又不需要暴露该对象的内部数据存储的实现。
- Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法,例如:用于获取第一个元素的first()方法,用于访问下一个元素的next()方法,用于判断是否还有下一个元素的hasNext()方法,用于获取当前元素的currentItem()方法等,在具体迭代器中将实现这些方法。
- ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
- Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
- ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
代码实现
Iterator类
public abstract class Iterator {
public abstract Object first();//得到开始对象
public abstract Object next();//得到下一个对象
public abstract boolean IsDone();//判断是否到达结尾
public abstract Object CurrentItem();//当前对象
}
Aggregate类
public abstract class Aggregate {
public abstract Iterator createIterator();//创建迭代器
}
ConcreteAggregate类
public class ConcreteAggregate extends Aggregate{
private int index;
private List<Object> items=new ArrayList<Object>();
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
public int getCount() {
return items.size();
}
public void setItems(int index,Object object) {
items.add(index,object);
}
public Object getItems(int index) {
return items.get(index);
}
}
ConcreteIterator类(具体迭代器类)
public class ConcreteIterator extends Iterator {
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
}
@Override
public Object first() {
return aggregate.getItems(0);
}
@Override
public Object next() {
Object object = null;
current++;
if (current < aggregate.getCount()) {
object = aggregate.getItems(current);
}
return object;
}
@Override
public boolean IsDone() {
return current >= aggregate.getCount() ? true : false;
}
@Override
public Object CurrentItem() {
return aggregate.getItems(current);
}
}
二、模式优缺点以及应用场景
应用场景:
- 当你需要访问一个聚集对象,而且不管这些对象时什么都需要遍历的时候,你就应该考虑用迭代器模式。
- 你需要对聚集有多种遍历时,可以考虑用迭代器模式。
- 希望对遍历不同的集合提供一个统一的接口。
优点
- 封装性好,对外部的使用者来说可以以相同的API来获取不同结构的数据集合中的数据元素,不需要关心遍历算法,简化了遍历方式
- 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,不需要修改原有的代码
缺点
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要增加对应的新的迭代器类,这样类的个数成对增加,会增加系统的复杂性。
- 对于简单的遍历,例如数组和有序列表,用迭代器的话比较繁琐,不如使用for循环等方法便利.。
三、迭代器模式在JDK源码中应用
1、Java Iterator统一了迭代方法,无论List中的Iterator,Map中的EntryIterator,都是迭代器实现。
2、MyBatis的源码包cursor就是迭代器模式的应用