我们首先来看看下面这段迭代打印字符串的代码
public static void print(Collection coll){
Iterator it = coll.iterator();
while(it.hasNext()){
String str = (String)it.next();
System.out.println(str);
}
}
其中就使用到了迭代器模式,正如上述代码一样,在集合中我们就频繁的使用到了迭代器模式。
特点与定义
- 定义:
提供一种方法顺序的访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。迭代器模式可以让用户通过特定的接口访问容器的数据,不需要了解容器内部的数据结构,是一种对象行为型模式。
- 问题由来
一般开发工作中,我们很少自定义迭代器,因为我们需要迭代功能的类都已经被内置了迭代器(如:list和set)。如果真的遇到这种需求需要我们自定义迭代器的话,可以参考jdk的迭代器实现方式来实现自己的迭代器。
迭代器是可以从前往后,或者从后往前遍历的。
参与角色
- 抽象容器(Aggregate):一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等
- 具体容器(ConcreteAggregate):就是抽象容器的具体实现类,完成对聚合对象的遍历,记录遍历的当前位置。比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
- 抽象迭代器(Iterator):定义遍历元素所需要的方法,一般包含 hasNext()、first()、next() 等方法。
- 具体迭代器(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。
- 类结构图
代码结构示例
定义抽象迭代器
interface Iterator { public Object next(); public boolean hasNext(); }
定义具体迭代器
class ConcreteIterator implements Iterator{ private List list = new ArrayList(); private int cursor =0; public ConcreteIterator(List list){ this.list = list; } public boolean hasNext() { if(cursor==list.size()){ return false; } return true; } public Object next() { Object obj = null; if(this.hasNext()){ obj = this.list.get(cursor++); } return obj; } }
定义抽象容器
//如:Collection,List,Set interface Aggregate { public void add(Object obj); public void remove(Object obj); public Iterator iterator(); }
定义具体容器
class ConcreteAggregate implements Aggregate { private List list = new ArrayList(); public void add(Object obj) { list.add(obj); } public Iterator iterator() { return new ConcreteIterator(list); } public void remove(Object obj) { list.remove(obj); } }
客户端调用
public class Client { public static void main(String[] args){ Aggregate ag = new ConcreteAggregate(); ag.add("小明"); ag.add("小红"); ag.add("小刚"); Iterator it = ag.iterator(); while(it.hasNext()){ String str = (String)it.next(); System.out.println(str); } } }
总结
优点
- 简化了遍历方式,遍历任务交由迭代器完成,访问一个聚合对象的内容无须清楚内部实现。
- 它支持以不同方式遍历一个聚合对象,比如有序列表,我们可以正序,倒序。
- 封装性良好,为遍历不同的聚合结构提供一个统一的接口,用户只需要得到迭代器就可以遍历,而对于具体聚合对象的遍历算法实现则不用去了解。
- 缺点
迭代器遍历,比传统的for循环遍历要更加繁琐,比如数组或有序列表
适用场景
- 一般有集合的地方就有迭代器,所以如果你想实现一个类似于集合的容器,那么集合的遍历则可以使用迭代器模式实现
- 迭代器模式在java的普通开发中没有使用机会,因为JDK已经帮我们提供了很多集合框架,这些集合框架中已经默认提供了迭代器,所以我们自定义实现迭代器模式的机会比较少。