前言
迭代器设计模式在 java 中算是使用最多的模式之一了。它主要应用在需遍历的数据集合中,迭代器模式封装了该数据集合的数据存储结构。用户只需关心该集合是否还有数据,如果有,取出下一个数据。
实现
迭代器模式实现十分简单,它将数据集合封装在迭代器中,并对外提供两个 hasNext() 和 next() 方法。hasNext() 返回集合中是否还有下一个数据,next() 取出集合中下一个数据。所以它的UMl
如下:
ConcreteIterator 是迭代器接口 Iterator 的具体实现类。Aggregate 容器类,它有一个生成迭代器的方法,它生成 ConcreteIterator 的实例,容器类拥有具体数据的集合,并把数据集合传给迭代器实现类ConcreteIterator。迭代器实现类拥有了具体数据集合后,变可对数据做逻辑处理。现在,假如有一个List 的数据集合需要遍历,该如何自己实现呢?(当然,java 自带了list的迭代器,不需要自定义实现,这里自己实现只是了解迭代器实现原理。先是迭代器接口类:
public interface Iterator {
public boolean hasNext();
public Object next();
}
接下来迭代器接口具体实现类。
public class DataIterator implements Iterator{
private List<Integer> itemList;
private int position;
public DataIterator(List<Integer> itemList){
this.itemList = itemList;
}
@Override
public boolean hasNext() {
if (position >= itemList.size()){
return false;
} else {
return true;
}
}
@Override
public Object next() {
return itemList.get(position++);
}
}
然后是生成迭代器的容器类,它拥有具体的数据集合。
public class Aggregate {
private List<Integer> list = new ArrayList<>();
...
public Iterator createIterator(){
return new DataIterator(list);
}
}
所以当用户要遍历容器类的集合时,
public class Main {
public static void main(String[] args){
Aggregate aggregate = new Aggregate();
Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()){
Integer i = (Integer) iterator.next();
System.out.println(i);
}
}
}
对于,对用户来说,它是不知道容器类 Aggregate 中的数据是用 list 还是数组亦或是 set存储的,它不知道内部的数据存储结构,它只关心关心 Aggregate 容器是否还有数据,有,取出下一个数据,直到遍历完。
案例
在具体工程开发过程中,我们可能会遇到接入其它接口时,或者在新老版本中,同一种类型的数据,存储在不同的集合中。比如,老版本中用数组存储该类型数据,结果在新版本用链表存储。而当我们需要遍历数据时,先遍历数组,再遍历链表。未来,没准就用set存储了,这时又得扩展遍历 set的代码。这种情况,工程扩展性差,而且多个遍历不同集合的 for 循环,代码也不雅观。这时,迭代器设计模式派上用场了。我们统计将不同的数据集合用迭代器封装,遍历不同存储结构的数据集合时,统一返回 Iterator,这样,遍历代码可以共用一套了,而不用多个 for 循环了。
while (iterator.hasNext()){
Object i = (Object) iterator.next();
...
}