迭代器模式
定义
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
什么时候用?
- 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
- 你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。
UML图
模板代码
Aggregate
/** * 聚集抽象类 * Created by callmeDevil on 2019/8/17. */ public abstract class Aggregate { // 创建迭代器 public abstract Iterator createIterator(); }
Iterator
/** * 迭代器抽象类 * Created by callmeDevil on 2019/8/17. */ public abstract class Iterator { // 用于定义得到开始对象、得到下一对象、判断是否到结尾、当前对象等抽象方法 public abstract Object first(); public abstract Object next(); public abstract boolean isDone(); public abstract Object currentItem(); }
ConcreteAggregate
/** * 具体聚集类 * Created by callmeDevil on 2019/8/17. */ public class ConcreteAggregate extends Aggregate { // 存放聚合对象 private List<Object> items = new ArrayList(); @Override public Iterator createIterator() { return new ConcreteIterator(this); } // 返回聚集的总个数 public int count() { return items.size(); } // 声明一个索引器 public Object get(int index) { return items.get(index); } public boolean set(Object o) { return items.add(o); } }
ConcreteIterator
/** * 具体迭代器类 * Created by callmeDevil on 2019/8/17. */ public class ConcreteIterator extends Iterator { // 定义一个具体聚集对象 private ConcreteAggregate aggregate; private int current = 0; public ConcreteIterator(ConcreteAggregate aggregate){ // 初始化时将具体的聚集对象传入 this.aggregate = aggregate; } @Override public Object first() { // 得到聚集的第一个对象 return aggregate.get(0); } @Override public Object next() { Object ret = null; current++; if (current < aggregate.count()) { // 得到聚集的下一个对象 ret = aggregate.get(current); } return ret; } @Override public boolean isDone() { // 判断当前是否遍历到结尾 return current >= aggregate.count(); } @Override public Object currentItem() { // 返回当前的聚集对象 return aggregate.get(current); } }
测试
public class Test { public static void main(String[] args) { // 公交车聚集对象 ConcreteAggregate a = new ConcreteAggregate(); // 新上来的乘客 a.set("路飞"); a.set("鸣人"); a.set("一护"); a.set("悟空"); a.set("纳兹"); a.set("琦玉"); // 售票员登场,看好上车的是哪些人,即声明迭代器对象 Iterator i = new ConcreteIterator(a); System.out.println(String.format("车位No.1乘客:%s", i.first())); while (!i.isDone()){ System.out.println(String.format("%s 来不及解释了,快上车!", i.currentItem())); i.next(); } } }
测试结果
车位No.1乘客:路飞 路飞 来不及解释了,快上车! 鸣人 来不及解释了,快上车! 一护 来不及解释了,快上车! 悟空 来不及解释了,快上车! 纳兹 来不及解释了,快上车! 琦玉 来不及解释了,快上车!
倒序遍历
ConcreteIteratorDesc
/** * 倒序具体迭代器 * Created by callmeDevil on 2019/8/17. */ public class ConcreteIteratorDesc extends Iterator{ // 定义一个具体聚集对象 private ConcreteAggregate aggregate; private int current = 0; public ConcreteIteratorDesc(ConcreteAggregate aggregate){ // 初始化时将具体的聚集对象传入 this.aggregate = aggregate; current = aggregate.count() - 1; //不同1 } @Override public Object first() { // 得到聚集的第一个对象 return aggregate.get(aggregate.count() - 1); //不同2 } @Override public Object next() { Object ret = null; current--; //不同3 if (current >= 0) { //不同4 // 得到聚集的下一个对象 ret = aggregate.get(current); } return ret; } @Override public boolean isDone() { // 判断当前是否遍历到结尾 return current < 0; //不同5 } @Override public Object currentItem() { // 返回当前的聚集对象 return aggregate.get(current); } }
测试
将顺序测试类中声明迭代器具体对象改为倒序的 ConcreteIteratorDesc 即可。
测试结果
车位No.1乘客:琦玉 琦玉 来不及解释了,快上车! 纳兹 来不及解释了,快上车! 悟空 来不及解释了,快上车! 一护 来不及解释了,快上车! 鸣人 来不及解释了,快上车! 路飞 来不及解释了,快上车!
总结
迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明的访问集合内部的数据。