迭代器模式的官方定义:
迭代器模式提供了一种方法,它能够顺序访问一个集合对象中的各个元素,并且又不暴露该对象的内部结构。
不使用迭代器模式实现容器的迭代:
当我们拿到一个含有集合的对象时,如果我们想要遍历对象中的集合,就必须要知道对象的内部结构,然后使用for循环遍历对象中的集合。而且当我们需要换一种遍历方式的时候(如:顺序遍历换成逆序遍历),需要修改客户端的代码,这就违背了“封闭-开放原则”。但如果使用了迭代器模式之后,需要换迭代方式时,只需要增加一个迭代器类,然后稍微修改一下集合对象中的代码,而客户端代码一句也不要动;也就是说,使用了迭代器模式之后,当需要更换迭代方式的时候,我们再增加一个类,而不是修改代码,从而体现了“开放-封闭原则”。
PS:开放-封闭原则:开放扩展,封闭更改。代码一旦写完就不要再去修改,若要增加功能,通过拓展继承体系(也就是增加类)来实现。
迭代器模式类图:
1.首先需要有一个存放许多数据的容器,我们把它称为Collection;其次需要再创建一个类,专门用来遍历容器中的数据,我们把这个类称为Iterator;而且Iterator中包含了遍历容器的一些基本函数。
2.由于容器的内部构造都不尽相同,但他们都需要使用迭代器遍历,因此我们抽象出容器们的公共接口,这个接口中只有一个获取迭代器的函数:iterator();
3.由于每个容器内部构造都不一样,所以迭代这些容器的迭代器的具体实现也不一样,所以我们需要为每一个容易简历一个专门的迭代器类,针对每种容器的内部结构,实现了Iterator接口中的函数。
4.由于具体的迭代器需要知道它所服务的容器的内部结构,所以要在构造迭代器的时候将容器的对象传给迭代器,迭代器拿到具体的容器对象之后,就可以根据这个容器的特性重写next、hasNext、first这些函数了。
5.最后,当迭代器和容器都写好之后,就可以交付给客户使用了。
客户通过容器的iterator函数获得该容器对应的迭代器对象,然后使用该迭代器对象的一些函数就可以遍历容器元素了。
PS:客户通过调用容器对象的iterator函数创建该容器对应的Iterator对象时,该容器的对象将会传递给Iterator对象:
private Iterator it;
@Override
public Iterator iterator() {
this.it = new AIterator(this);
return this.it;
}
当AIterator对象获取到它所服务的容器对象之后,才能针对该容器的结构重写next、hasNext、first这些函数。
迭代器模式的好处:
1.如果要更换一个具体容器的迭代方式的时候,客户端不需要做任何改动,还是这么写:
Iterator it = collection.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
我们只需要:
a)再创建一个迭代器类,重写里面的next、hasNext、first这些函数;
b)然后让容器类的iterator函数中创建Iterator对象时,将“旧的Iterator”换成“新的Iterator”
public Iterator iterator(){
this.it = new 新的Iterator();
}
因此,一个容器的迭代方式换了之后,不影响客户端的代码,降低了客户端与Iterator类和Collection类的耦合。
2.迭代器模式将集合对象的遍历行为单独封装在一个类中,这样既不暴露集合的内部结构,又可以使外部代码透明地访问集合内部的数据。