Head First 设计模式学习笔记(十)迭代器模式
1.当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历时,就应该考虑用迭代器模式。
?
2.当需要对聚集对象有多种遍历方式时,可以考虑用迭代器模式。
?
3.迭代器模式在访问数组,集合,列表等数据时,尤其是数据库数据操作时,是非常普遍的应用,???各种高级语言 都对它? 进行了封装,反而给人感觉此模式本身不太常用。
?
?
?
1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。迭代器的抽象是为了迭代器不依赖于容器的内部结构
2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。
迭代器遍历容器元素,所以迭代器必须知道容器元素的内部细节,所以具体容器与具体的迭代器是耦合的。
?
而在Java Collection的应用中,提供的具体迭代器角色是定义在容器角色中的内部类。这样便保护了容器的封装。但是同时容器也提供了遍历算法接口,你可以扩展自己的迭代器。
好了,我们来看下Java Collection中的迭代器是怎么实现的吧。
?
1、//迭代器角色,仅仅定义了遍历接口
public abstract class AbstractList extends AbstractCollection implements List {…… //这个便是负责创建具体迭代器角色的工厂方法public Iterator iterator() { return new Itr();}//作为内部类的具体迭代器角色private class Itr implements Iterator { int cursor = 0; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public Object next() { checkForComodification(); try { Object 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(); }}
?
3、至于迭代器模式的使用。正如引言中所列那样,客户程序要先得到具体容器角色,然后再通过具体容器角色得到具体迭代器角色。这样便可以使用具体迭代器角色来遍历容器了……
4、实现自己的迭代器:
在实现自己的迭代器的时候,一般要操作的容器有支持的接口才可以。而且我们还要注意以下问题:
在迭代器遍历的过程中,通过该迭代器进行容器元素的增减操作是否安全呢?
在容器中存在复合对象的情况,迭代器怎样才能支持深层遍历和多种遍历呢?
以上两个问题对于不同结构的容器角色,各不相同,值得考虑。