1 定义
迭代器模式(Iterator Pattern)属于行为型设计模式,它主要是为了解决在不暴露对象内部表示情况下,提供一种方法可顺序来访问一个聚合对象里的各个元素,简单地说就是为一个聚合对象提供对外可遍历它里内元素的方案。像我们常使用的for语句中,i++每次循环自增迭代到下一个元素,将这种循环变量的作用抽象后通用化就是迭代器模式。正如有些场景下我们并不想关心一个聚合对象内部使用是List、set还是Map的集合存储方式,只想使用统一的遍历方法对此聚合对象进行内部元素的遍历。例如现实场景有一学校,局里的人希望知道学校里所有的学生信息,那么局里的人并不需要专门跑进学校教务室里去了解保存学生信息是通过电脑还是实体文件的方式,然后对应哪种方式再进行翻查信息,而只需要让学校对外提供出来学生信息的查询的渠道和具体操作即可。
2 实现
迭代器模式一般包含了4个角色,分别是:
- 抽象迭代器(Iterator):用于定义得到下一对象和判断是否到最后对象的统一遍历集合的接口。
- 具体迭代器(Concretelterator):继承抽象迭代器,实现相关遍历接口。例如上述定义举例的学校要对外提供每个学生信息的渠道的具体遍历方案。
- 抽象聚合(Aggregate):用于定义标识聚合的接口,定义可获取迭代器的接口。
- 具体聚合(ConcreteAggregate):继承抽象聚合,实现获取迭代器的接口且内部维护着一个集合。例如上述定义举例的学校要对外提供每个学生信息的渠道。
抽象迭代器,声明了迭代的统一遍历方法:
public interface Iterator {
boolean hasNext();
Object next();
}
具体迭代器,内部持有具体聚合对象的引用,根据实现的统一遍历方法来对聚合对象进行相应的操作:
public class SchoolIterator implements Iterator {
private SchoolAggregate mSchoolAggregate;
private int mIndex;
public SchoolIterator(SchoolAggregate schoolAggregate) {
mSchoolAggregate = schoolAggregate;
mIndex = 0;
}
@Override
public boolean hasNext() {
if (mIndex < mSchoolAggregate.getLength()) {
return true;
} else {
return false;
}
}
@Override
public Object next() {
return mSchoolAggregate.getStudentAt(mIndex++);
}
}
抽象聚合,声明了获取迭代器的接口方法:
public interface IAggregate {
Iterator iterator();
}
具体聚合,内部维护着一份数组或集合,以及实现具体获取迭代器的方法:
public class SchoolAggregate implements IAggregate {
private List<String> mStudents;
public SchoolAggregate() {
mStudents = new ArrayList<>();
}
public String getStudentAt(int index) {
return mStudents.get(index);
}
public void appendStudent(String student) {
mStudents.add(student);
}
public int getLength() {
return mStudents.size();
}
@Override
public Iterator iterator() {
return new SchoolIterator(this);
}
}
客户端:
public class Main {
public static void main(String[] args) {
SchoolAggregate schoolAggregate = new SchoolAggregate();
schoolAggregate.appendStudent("小明");
schoolAggregate.appendStudent("小红");
schoolAggregate.appendStudent("小文");
schoolAggregate.appendStudent("小强");
schoolAggregate.appendStudent("小微");
schoolAggregate.appendStudent("小小");
System.out.println("学校有学生:");
Iterator it = schoolAggregate.iterator();
while (it.hasNext()) {
String student = (String) it.next();
System.out.println(student);
}
}
}
输出结果:
学校有学生:
小明
小红
小文
小强
小微
小小
3 总结
迭代器模式在访问数组、集合等数据时,特别是对数据库操作时是非常普遍的使用,它将集合遍历行为与实现逻辑分离开来,抽象出一个迭代器类来负责,使不暴露集合的内部结构,又可让外部代码透明地访问集合内部数据。也正因为它的普遍性,所以很多语言本身就已提供现成的封装,例如Java就提供了现成的迭代器类:java.util.Iterator。因为如果需要增加新的聚合类就得对应增加新的迭代器类,类的个数成对增加,所以这在一定程度上也增加了系统的复杂性。