迭代器模式就是一种在不暴露集合底层结构形式(数组、队列、栈、链表、树等)的情况下提供的获取、遍历集合元素的方法,比如我们需要遍历一个树可以采用深度优先(DFS)或广度优先 (BFS)搜索算法,如下图:
这样我们在遍历时就需要考虑算法的实现,所以如果我们在容器类中提供一些简单访问接口,并提供不同迭代器去调用接口实现不同的遍历,这样对于迭代器的使用这就会显得非常简单,因为他不用去考虑底层结构,只需要使用迭代器统一接口就可以完成不同的遍历。
下面是传统迭代器模式的UML图:
常见的迭代器实现使用可参考C++的STL中各种容器类中迭代器的实现或者Qt中容器迭代器模式(Qt里既有STL风格的迭代器实现也有Java风格的迭代器实现)。下面就是Qt中QListIterator和QMapIterator迭代器类的使用例子截图:
这是Qt中提供的Java风格的迭代器,我们可以发现我们遍历不同的数据结构使用的方法确大同小异,使用起来就方便多了(因为无需考虑底层算法的实现了),有更好的封装性,但随之产生的缺点就是当与某些简单集合(数组、有序列表等),使用迭代器的方式就没直接遍历来得简单同时效率也因为结构的复杂而降低,这也就印证了人们常说的一个人的优点可能就是他的缺点,而他的缺点也可能正是他的优点。
我们可以参考上面迭代器类的使用为C++中list实现一个Java风格的迭代器类使用,这种实现方式与使用较为简单,下面是具体代码操作:
1. 抽象迭代器接口类定义(传统迭代器模式实现需要定义)
2. 具体迭代器类定义:ListIterator
这里实现ListIterator中使用了stl中list自带的iterator的原因是基于C++中list提供的操作接口决定,因为我们是直接为它另外实现一个迭代器遍历模型,这里面不可避免会访问其任意位置的元素,而C++中list提供的可以访问到任意元素位置的就是它自带的迭代器。
3. 主函数功能测试代码
程序运行结果:
上面代码我们选用的泛型编程,细心的朋友会发现这里写的跟UML图中的迭代器模式结构有些不一样(没有实现集合类Collection),这是因为为了结构简单具体集合类我在这里是直接使用的C++里的list,所以集合类Collection就没有去单独实现了;另外这里其实也可以不用定义Iterator这个抽象类,直接编写一个模板类ListIterator即可;我们实现不同迭代器的目的就是灵活实现不同的容器遍历方式,如果按传统的实现通过抽象类提供统一接口调用,这样就会涉及到多态中虚函数调用,带来性能成本的增加,这里写上的原因是为了与前面迭代器模式的UML图结构对应。下面再给大家提供一个STL中list的简单实现来看看C++中list自带的iterator的实现,这里需重新实现了list所以代码相对较多,list实现就主要参考双向循环链表的写法,这里配合上模板使用即可,具体代码如下:
程序运行结果:
上面就是参考C++及Qt容器中迭代器使用而实现的迭代器模式,仅供学习参考。