学习迭代器设计模式后的再学习
任何容器类,必须有某种方式可以插入元素并将他们再次取回。例如,对于List,add是它的一个插入方法,而get是他的一个元素取出方法。
但经过思考会发现问题,这样的话会有个缺点:要使用容器,必须对容器的确切类型编程,起初看来没什么不好。但假设一个程序原本对着list编程,后来却改为对set编程,怎么样才能显得更方便一些呢?如果有个容器,我们称之为容器C没有实现当前方法绑定的接口,那你就得去方法里面把容器数据访问代码改成符合这个容器C的了。那么就不应该关注容器的类型,从而有了新的操作方式。
迭代器的概念可以达成此目的,从而我们引入了迭代器模式。迭代器是一个对象,他的工作是遍历并选中序列中的对象,而客户端程序员不必知道或关系该序列底层的结构。此外,爹大气通常被称为轻量级对象,因为创建它的代价较小。因此。经常可以看见对迭代器有些奇怪的限制。例如,java的Iterator只能单向移动,且只能用来:
1)使用方法iterator()要求容器返回一个Iterator.Iterator讲返回准备好返回序列的第一个元素。
2)使用next()获得序列的下一个元素。
3)使用hasnext()检查序列纵是否还有元素。
4)使用remove()讲迭代器新近返回的元素删除。
有了迭代器,就不用担心容器中元素数量的问题了,这就由hasNext()和next()关心的事情。但假设遍历一个容器且不修改容器对象本身,那么for-each语句反而会显得更加简洁。但当想要修改容器时,在for-each语句中使用remove会带来一些不必要的麻烦。而Iterator还可以一处由next()产生的最后一个元素,这意味着调用remove前还需要调用一次next。
既然Iterator功能如此强大,那可以考虑创建一个方法使它不必知晓容器的具体类型:。
如下图所示,是我在文本文档中设计的一个不必知晓容器的确切类型:
除此之外,ListIterator是一个更加强大的Iterator的子类型,它只能用于各种List的访问。尽管Iterator只能向前移动,而ListIterator可以双向移动。且可以产生相对于迭代器在列表中指向当前位置的前一个和后一个元素的索引。并且可以使用set()方法替换它访问过的最后一个元素。你可以通过调用ListIterator()放大产生一个指向list开始处的ListIterator,并且可以通过调用ListIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。