一、动机
在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。
使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式
二、模式定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露(稳定)该对象的内部表示。
三、结构
四、要点总结
迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。
五、代码示例
先来创建抽象迭代器 MyIterator
public interface MyIterator<E> {
void reset(); //重置为第一个元素
E next(); //获取下一个元素
E currentItem(); //检索当前元素
boolean hasNext(); //判断是否还有下一个元素存在.
}
接下来,我们再来定义抽象集合 MyList,也声明为泛型接口,接收类型参数 E,声明一个创建迭代器 MyIterator 的方法 iterator()。
public interface MyList<E> {
MyIterator<E> iterator();
}
然后,我们构造一个对象 Topic,对象中只包含 name 属性以及其构造函数和 get、set 方法。
public class Topic {
private String name;
public Topic(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
再接着实现一个具体的迭代器类 TopicIterator,其中包含属性为 Topic 的数组和一个记录对象存储位置的对象 position。当我们执行 next() 方法时,会获取当前记录位置的对象,至于 reset() 则会重置对象在数组中的位置为 0,currentItem() 方法则会返回当前位置下的对象,hasNext() 则判断当前位置是否越界。
public class TopicIterator implements IteratorIterator<Topic> {
private Topic[] topics;
private int position;
public TopicIterator(Topic[] topics) {
this.topics = topics;
position = 0;
}
@Override
public void reset() {
position = 0;
}
@Override
public Topic next() {
return topics[position++];
}
@Override
public Topic currentItem() {
return topics[position];
}
@Override
public boolean hasNext() {
if(position >= topics.length) {
return false;
}
return true;
}
}
同样,还需要实现一个具体的集合类 TopicList,该类中只实现一个创建迭代器的方法,返回对应具体迭代器的类方法。
public class TopicList implements ListList<Topic>{
private Topic[] topics;
public TopicList(Topic[] topics)
{
this.topics = topics;
}
@Override
public IteratorIterator<Topic> iterator() {
return new TopicIterator(topics);
}
}
最后,我们再来运行一段单元测试:
public class Client {
public static void main(String[] args) {
Topic[] topics = new Topic[5];
topics[0] = new Topic("topic1");
topics[1] = new Topic("topic2");
topics[2] = new Topic("topic3");
topics[3] = new Topic("topic4");
topics[4] = new Topic("topic5");
MyList<Topic> list = new TopicList(topics);
MyIterator<Topic> iterator = list.iterator();
while(iterator.hasNext()) {
Topic currentTopic = iterator.next();
System.out.println(currentTopic.getName());
}
}
}
//输出结果
topic1
topic2
topic3
topic4
topic5