1.迭代器模式的定义
迭代器模式提供一种对容器对象中的各个元素进行访问的方法,而不需要暴露该对象的内部细节;
在软件系统中,容器对象有两个职责:一是存储数据,二是遍历数据;从依赖性上看,前者是基本职责,而后者是可以变化的,又是可以分离的,因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则;
对于迭代器模式,设计时很少用到,但编码时经常用到,目前大多数编程语言中,迭代器已经成为一个基础的类库,直接能用来遍历集合对象;
1.1 迭代器模式的优缺点
优点
- 迭代器模式支持以不同方式遍历一个集合对象,在同一个集合对象上可以定义多种遍历方式,在迭代器模式中只需要用一个不同的迭代器来替换原有的迭代器,即可改变遍历算法,也可以自己定义迭代器的子类以支持新的遍历方式;
- 迭代器简化了集合类,原有的集合对象不需要再自行提供数据遍历等方法;
- 由于引入了抽象层,增加新的集合类和迭代器类都很方便,无需修改原有代码,满足基于接口编程而非实现和开闭原则;
缺点
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加了类的个数,增加了系统的复杂性;
- 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展;
1.2 迭代器模式的使用场景
- 减少程序中重复的遍历代码;
- 当需要为遍历不同的集合结构提供一个统一的接口时或当访问一个集合对象的内容而无需暴露其内部细节时;
2.迭代器模式的原理
- 抽象集合类(Aggregate):用于存储和管理元素对象,定义存储、添加、删除集合的功能,并且声明了一个 createIterator() 方法用于创建迭代器对象;
- 具体集合类(ConcreteAggregate):实现抽象集合类,返回一个具体迭代器的实例;
- 抽象迭代器类(Interator):定义访问和遍历集合元素的接口,通常包含 hasNext()、next() 等方法;
- 具体迭代器类(ConcreteIterator):实现抽象迭代器接口所定义的方法,完成对集合对象的遍历,同时记录遍历的当前位置;
3.迭代器模式的实现
【代码】
抽象迭代器
java
public interface IteratorIterator<E> {
void reset(); //重置为第一个元素
E next(); //获取下一个元素
E currentItem(); //检索当前元素
boolean hasNext(); //判断是否还有下一个元素存在
}
抽象集合
java
public interface ListList<E> {
//获取迭代器对象的抽象方法(面向接口编程)
IteratorIterator<E> Iterator();
}
具体迭代器
java
public class TopicIterator implements IteratorIterator<Topic> {
//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;
}
}
抽象迭代器
java
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);
}
}
客户端
java
public class Client {
public static void main(String[] args) {
Topic[] topics = new Topic[4];
topics[0] = new Topic("topic1");
topics[1] = new Topic("topic2");
topics[2] = new Topic("topic3");
topics[3] = new Topic("topic4");
TopicList topicList = new TopicList(topics);
IteratorIterator<Topic> iterator = topicList.Iterator();
while(iterator.hasNext()){
Topic t = iterator.next();
System.out.println(t.getName());
}
}
}