五十二:迭代子Iterator模式
迭代子Iterator模式又叫做游标模式,是对象的行为模式,迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表像.
Java聚集(Collection)对象是实现了共同的java.util.Collection接口的对象,从1.2版本开始,Java语言提供了很多种聚集,包括Vector,ArrayList,Queue,Stack,TreeSet,HashMap,TreeMap...那么为什么聚集需要迭代子??聚集对象必须提供适当的方法,允许客户端能够按照一个线性顺序遍历所有的元素对象,把一个元素对象提取出来或者删除掉,一个使用聚集的系统必然会使用这些方法操控聚集对象,回而在使用聚集的系统深化过程中,会出现两类问题:
(1)迭代逻辑没变,但是需要将一种聚集换成另一种聚集时,由于不同的聚集有不同的接口,所以要修改客户端代码
(2)聚集不会改变,但是迭代的方式需要改变。比如原来只有读取和删除元素,而现在要对元素进行过滤,这时就只好修改聚集对象,修改已有的遍历方法...造成这样的原因,是因为没有将不变的结构从系统中抽象出来与可变成分分割,并将可变部分的各种实现封装起来.迭代子模式把迭代逻辑封装到一个独立的迭代子对象中,从而与聚集本身分割开。迭代子对象是对遍历的抽象化,不同的聚集对象可以提供相同的迭代子对象,从而使客户端无需知道聚集的底层结构,一个聚集可以提供多个不同的迭代子对象,从而使得遍历逻辑的变化不会影响到聚集对象本身.
再论“开闭”原则:开闭原则要求系统可以在不修改已有代码的情况下进行功能的扩展,做到这一点的途径就是对变化的封装
(1)从对变化的封装角度讲,迭代子模式将访问聚集元素的逻辑封装起来,并且使它独立于聚集对象的封装,这就提供了聚集存储逻辑与迭代逻辑独立演变的空间,增加了系统的可复用性..
(2)从代码的重构角度上讲,迭代子在客户端和聚集之间增加了一个中介层,从而使得客户端与聚集之间的通信从直接变成间接,这样做的好处就是缓冲了客户端的对聚集的影响,以及聚集的变化对客户端的影响.
迭代子模式涉及到以下几个角色:
(1)抽象迭代子(Iterator)角色:此抽象角色定义出遍历元素所需要的接口.
(2)具体迭代子(ConcreteIterator)角色:此角色实现了Iterator接口,并保持迭代过程中的游标位置.
(3)聚集(Aggregate)角色:此抽象角色给出创建迭代子(Iterator)对象的接口.
(4)具体聚集(ConcreteAggregate)角色:实现了创建迭代子(Iterator)对象的接口,返回一个合适的具体迭代子实例
(5)客户端(Client)角色:持有对聚集及其迭代子对象的引用,调用迭代子对象的迭代接口,也有可能通过迭代子操作聚集元素的增加和删除.
示意源码如下:
package cai.milenfan.basic.test; public class Client{ private Iterator it; private Aggregate agg = new ConcreteAggregate(); public void operation(){ it = agg.createIterator(); while( !it.isDone() ){ System.out.println(it.currentItem().toString()); it.next(); } } public static void main(String[] args){ Client client = new Client(); client.operation(); } }