什么是迭代器模式?
迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
没有迭代器的时代,我们是怎么遍历容器的
for (int i = 0; i< arrayList.size(); ++i) {
System.out.println(arrayList.get(i));
}
我们需要关心容器内部的方法size(),get()
这样用户去使用容器就和容器强耦合了,必须去了解容器的内部。
迭代器解决什么问题?两种迭代器
从定义可见,迭代器模式是为容器而生。
迭代器解决的问题就是在不关心对象内部细节的情况下去遍历容器。
你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。
然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。
而迭代器模式的出现,很好的解决了上面两种情况的弊端。先来看下迭代器模式的真面目吧。
迭代器模式应用举例
内部迭代器
这种我不像说了,就是在容器内部实现自己的迭代算法,客户端去调用就可以了。缺点是迭代形式单一,死板
外部迭代器
我个人比较推崇外部迭代器
Java Collections容器中就是利用了外部迭代器去进行容器访问的
JDK中提供了一个迭代器接口
public interface Iterator<E> { boolean hasNext(); E next(); void remove(); }
这个迭代器可以根据不同的容器有不同的内部实现,例如Itr实现了Iterator<E>
private class Itr implements Iterator<E> { int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
这个具体的迭代器类作为一个轻量级容器组合在需要迭代功能的容器中,例如AbstractList,用户可以通过
public Iterator<E> { return new Itr(); }
得到具体的迭代器,在JVM运行时的时候可以得到具体的迭代器,用户得到具体的迭代器后,就可以通过迭代器接口中提供的方法去操纵容器了
JDK的这种迭代器实现又叫做多态迭代器。即可以在运行时,可以通过不同的容器的iterator()方法得到具体该容器的轻量级迭代器。
这样用户无需关心容器的内部实现,就可以去访问遍历容器