设计模式系列(十三)迭代器模式(Iterator Pattern)
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露器内部的表示。也就是说,迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部的表示,把游走的任务放在迭代器上,而不是聚合上,这样就简化了聚合的接口和实现,也让责任各得其所。
学过面向对象编程语言的朋友一定对迭代器这个设计深有体会,在C++中的STL中很多地方都用到了迭代器,如果大家想看到更多的迭代器的优秀的实例可以参考STL的源码,会受益匪浅。在C++中的集合,如vector、list、queue等,都有迭代器,我们只需要获取它们的迭代器,就可以对其进行遍历以及其他操作。大家从这个角度想一想,是不是我们在使用不同的集合时,不用管太多的细节,直接获取迭代器,然后就可以按照固定或类似的形式进行遍历或者其他操作,这样就体现了设计模式的理念,封装性比较好,对于用户来说不需要知道底层的细节,只需要知道怎么使用即可,而且STL内部的细节自然就不会暴露给我们,接口统一,方便使用,是不是觉得在C++中用迭代器进行了很多操作,那你就是其中的受益者,这也是迭代器模式的体现。
迭代器模式中有四个角色:
(1)Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法,在具体迭代器中将实现这些方法。
(2)ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
(3)Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
(4)ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
从上面这几个角色可以看出,其实迭代器模式使用了类似于工厂方法模式的那种架构,在抽象类中定义了一个抽象方法,然后延迟到子类实现。这里有几个概念需要说明一下。首先,这里说的聚合类就类似于我们见得vector、list等,当然,聚合类不局限于这些我们见到的集合,它还可以是自己定义的一个聚合类,自己实现其中的操作;其次,这里说的迭代器就是针对于每种聚合类的迭代器,每种聚合类都要实现一个具体的迭代器类。
迭代器模式的优点有:
(1)它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
(2)迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
(3)在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。
迭代器模式的缺点有:
(1)由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
(2)抽象迭代器的设计难度较大,