迭代器模式
定义
在软件构建过程中,集合对象内部结构常常变化各异,但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为同一种算法在多种集合对象上进行操作提供了可能。
迭代子(Iterator)模式又叫游标(Cursor)模式,是对象的行为模式。迭代子模式可以顺序地访问一个聚集中的元素而不必暴漏聚集的内部表象。
聚集
-
多个对象聚在一起形成的总体称之为聚集(Aggregate),聚集对象是能够包容一组对象的容器对象。聚集依赖于聚集结构的抽象化,具有复杂化和多样性。数组就是最基本的聚集,也是其他的JAVA聚集对象的设计基础。
-
JAVA聚集对象是实现了共同的java.util.Collection接口的对象,是JAVA语言对聚集概念的直接支持。从1.2版开始,JAVA语言提供了很多种聚集,包括Vector、ArrayList、HashSet、HashMap、Hashtable等,这些都是JAVA聚集的例子。
类图
借用网上一张图,可参考
角色
-
抽象迭代子(Iterator)角色:此抽象角色定义出遍历元素所需的接口。
-
具体迭代子(ConcreteIterator)角色:此角色实现了Iterator接口,并保持迭代过程中的游标位置。
-
聚集(Aggregate)角色:此抽象角色给出创建迭代子(Iterator)对象的接口。
-
具体聚集(ConcreteAggregate)角色:实现了创建迭代子(Iterator)对象的接口,返回一个合适的具体迭代子实例。
-
客户端(Client)角色:持有对聚集及其迭代子对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除。
示例
迭代器借口
public interface MyIterator {
public Object previous();
public Object next();
public boolean hasNext();
public Object first();
}
具体迭代器实现类
public class MyIteratorImpl implements MyIterator {
private MyCollection collection;
private int position = -1;
public MyIteratorImpl(MyCollection collection) {
this.collection = collection;
}
@Override
public Object previous() {
if(--position < 0){
System.err.println("无上一个元素");
return null;
}
return collection.get(position);
}
@Override
public Object next() {
if(++position > (collection.size()-1)){
System.err.println("无下一个元素");
return null;
}
return collection.get(position);
}
@Override
public boolean hasNext() {
if((position+1) > (collection.size()-1)){
return false;
}
return true;
}
@Override
public Object first() {
position = 0;
return collection.get(0);
}
}
集合接口
public interface MyCollection {
public MyIterator iterator();
public Object get(int index);
public int size();
}
集合实现类
public class MyCollectionImpl implements MyCollection {
private MyIterator iterator ;
private Object[] objects;
public MyCollectionImpl(Object[] objects) {
this.iterator = new MyIteratorImpl(this);
this.objects = objects;
}
@Override
public MyIterator iterator() {
return iterator;
}
@Override
public Object get(int index) {
return objects[index];
}
@Override
public int size() {
return objects.length;
}
}
测试类
public class MyIteratorTest {
public static void main(String[] args) {
Object[] objects = {1,2,3,4,5,6,7,8,9};
//这里直接传入固定的数组,实际中可以在Collection接口中增加add方法动态增加元素,不过需要动态数组支持,这里暂时简化
MyCollectionImpl myCollectionImpl = new MyCollectionImpl(objects);
MyIterator iterator = myCollectionImpl.iterator();
while(iterator.hasNext()){
int next = (Integer)iterator.next();
System.out.println(next);
}
}
}
分析
-
迭代子模式简化了聚集的接口。迭代子具备了一个遍历接口,这样聚集的接口就不必具备遍历接口。
-
每一个聚集对象都可以有一个或多个迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。因此,一个聚集对象可以同时有几个迭代在进行之中。
-
由于遍历算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化。