GOF 在《设计模式》:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
迭代器模式 是对象行为模式。
聚合:是指一组对象的组合结构,比如:java 中的集合,数组等。
思想:迭代模式的关键思想就是把聚合对象的遍历个访问从聚合对象中分离出来,放入单独的迭代器中。
功能:以不同的方式遍历聚合对象,比如向前、向后等。
对同一对象进行多个遍历。
以不同的遍历策略来遍历聚合对象,比如是否需要过滤等。
多太迭代:为不同的聚合结构提供统一的迭代接口。
Iterator:迭代器接口。定义访问和遍历元素的接口。
ConcreteIterator:具体的迭代器实现对象。实现对聚合对象的遍历,并跟踪遍历时的当前位置。
Aggregate:聚合对象。定义创建相应迭代器对象的接口。
ConcreteAggregate:具体的聚合对象。实现创建相应的迭代器对象。
/**
* 迭代接口,定义访问和遍历元素的操作
*/
public interface Iterator<T> {
/**
* 移动到聚合对象的第一个位置
*/
public void first();
/**
* 移动到聚合的下一个位置
*/
public void next();
/**
* 判断是否已经移动到聚合对象的最后一个位置
* @return
*/
public boolean isLast();
/**
* 获取迭代的当前元素
* @return 迭代的当前元素
*/
public T currentItem();
}
/**
* 具体的迭代器实现对象,不同的聚合对象相应的迭代实现不一样
*/
public class ConcreteIterator<T> implements Iterator<T> {
/**
* 持有被迭代的具体的聚合对象
*/
private ConcreteAggregate<T> aggregate;
/**
* 内部索引,记录当前迭代到得索引位置
* -1表示刚开始的时候,迭代器指向聚合对象第一个对象之前
*/
private int index = -1;
public ConcreteIterator(ConcreteAggregate<T> aggregate){
this.aggregate = aggregate;
}
@Override
public void first() {
index = 0;
}
@Override
public void next() {
if(index < this.aggregate.size()){
index = index + 1;
}
}
@Override
public boolean isLast() {
if(index == this.aggregate.size()){
return true;
}
return false;
}
@Override
public T currentItem() {
return this.aggregate.get(index);
}
}
/**
* 聚合对象的接口,定义创建相应迭代器对象的接口
*/
public abstract class Aggregate<T> {
/**
* 工厂方法,创建相应迭代器对象的接口
* @param <T>
* @return 相应迭代器对象的接口
*/
public abstract Iterator<T> createIterator();
}
/**
* 具体的聚合对象,实现创建相应迭代器对象的功能
*/
public class ConcreteAggregate<T> extends Aggregate<T> {
/**
* 聚合对象的具体内容
*/
private T[] ss = null;
public ConcreteAggregate(T[] ss) {
super();
this.ss = ss;
}
@Override
public Iterator<T> createIterator() {
//实现创建Iterator的工厂方法
return new ConcreteIterator<T>(this);
}
/**
* 获取索引所对应的元素
* @param index 索引
* @return 索引所对应的元素
*/
public T get(int index){
T retObj = null;
if(index < ss.length){
retObj = ss[index];
}
return retObj;
}
/**
* 获取聚合对象的大小
* @return 聚合对象的大小
*/
public int size(){
return this.ss.length;
}
}
public class Client {
public static void main(String[] args) {
Long[] names = {100L, 120L, 130L};
Aggregate<Long> aggregate = new ConcreteAggregate<Long>(names);
Iterator<Long> it = aggregate.createIterator();
it.first();
while(!it.isLast()){
Long obj = it.currentItem();
System.out.println("the obj==" + obj);
it.next();
}
}
}
迭代器模式的优点有:
- 简化了遍历方式,对于对象集合的遍历,还是比较麻烦的,对于数组或者有序列表,我们尚可以通过游标来取得,但用户需要在对集合了解很清楚的前提下,自行遍历对象,但是对于hash表来说,用户遍历起来就比较麻烦了。而引入了迭代器方法后,用户用起来就简单的多了。
- 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。
- 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。
迭代器模式的缺点:
- 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,大家可能都有感觉,像ArrayList,我们宁可愿意使用for循环和get方法来遍历集合。