迭代器模式
定义
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
什么时候用?
- 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。
- 你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。
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乘客:琦玉
琦玉 来不及解释了,快上车!
纳兹 来不及解释了,快上车!
悟空 来不及解释了,快上车!
一护 来不及解释了,快上车!
鸣人 来不及解释了,快上车!
路飞 来不及解释了,快上车!
总结
迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明的访问集合内部的数据