迭代子模式为遍历聚集提供了统一的接口方法,从而使得客户端不需要知道聚集的内部结构就能就能对聚集进行遍历等操作。
迭代子模式的结构 :
一般结构:
涉及到的角色解释:
抽象迭代子(Iterator)角色:定义了遍历聚集的接口。
具体迭代子(ListIterator)角色:实现了抽象迭代子接口。
抽象聚集(Collection)角色:定义聚集的公共方法,并为聚集创建迭代子(Iterator)对象。
具体聚集(ArrayList)角色:能够返回一个实现迭代子(Iterator)接口的迭代子实例。
客户端(Client)角色:持有对聚集和迭代子实例的引用,通过迭代子对聚集进行迭代。
一个例子:
类图:
抽象迭代子(Iterator)角色:
具体迭代子(ListIterator)角色:
抽象聚集(Collection)角色:
具体聚集(ArrayList)角色:
客户端(Client)角色:
内禀子,外禀子?
内禀子:聚集本身不提供访问其内部元素的方法,只有通过聚集内部的迭代子来遍历聚集,这时迭代子是个内部类,是聚集的一部分。
外禀子:聚集本身提供访问其内部元素的方法,可以通过外部的迭代子来遍历聚集,这时迭代子是个外部类,只维持对聚集的一个引用。
显然,我们上面的例子是一个外禀迭代。
java内部的ArrayList类用的是一个内禀子迭代子。
在jdk中,ArrayList类继承抽象类AbstractList,而在AbstractList中,有一个内部类Itr:
内禀子VS外禀子
迭代子有一个很重要的属性就是当前聚集的指针,有了当前的指针,才能进行迭代。如果几个客户端同时迭代一个聚集,假如聚集的迭代子是外禀子,这个是没有问题的,几个客户端持有每个外禀子的独立指针。但是如果聚集的迭代子是内禀子,问题就出现了:几个客户端同时持有内禀子的指针,并且同时对指针进行操作,就不能正常的对集合进行遍历。
使用外禀迭代子的一个重要理由是它可以被几个不同的方法和对象共享和控制,使用内禀子的优点是它不破坏对聚集的封装。
java的设计师在设计AbstractList的时候在聚集定义了内部类Itr作为迭代子,也就是说,设计师不希望客户端随意更换迭代子。
项目源码下载:http://cid-2c8a0dc7c1eb1d71.skydrive.live.com/self.aspx/soft/Design%20Pattern/Iterator.7z