定义
迭代器模式为遍历不同的容器结构提供统一的接口,提供一种方法顺序访问聚合对象中的各个元素,而又不暴露聚合对象内部的表示。迭代器模式的核心思想是数据的存储和遍历分离,同其他设计模式类似,迭代器的分离操作的优缺点共存。
需要注意的是,因为每一个聚合对象的底层存储结构不同,因为需要为每一个聚合对象提供对应的迭代器。
- 优点
聚合对象只负责存储,遍历由迭代器完成,这就将聚合对象保护起来,外部用户使用只需调用迭代器即可。 - 缺点
遍历操作从聚合对象中剥离出去,由单独的迭代器类完成。这就增加了类的数量,进而增加系统的复杂性。
模式结构
迭代器模式主要包含以下角色。
- 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
- 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
- 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
- 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
这四个结构的关系如下图
代码实践
迭代器模式的结构比较简单,根据模式结构创建对应的类即可。为突出重点,不适用泛型,直接假设聚合对象中存储的是Student类,因此只需创建5个类即可。
-
抽象迭代器接口
/** * @description: 集合迭代器接口 * 该类定义了两个实现迭代操作的两个关键方法 * @Date: 2021/10/14 16:17 */ public interface AggregateIterator { Student nextStudent(); boolean isLastStudent(); }
-
具体迭代器实现类
/** * @description: 学生集合类的迭代器的实现接口 * @Date: 2021/10/14 16:18 */ public class StudentAggregateIteratorImpl implements AggregateIterator { private List<Student> studentList; int position; Student student; public StudentAggregateIteratorImpl(List<Student> studentList){ this.studentList = studentList; } @Override public Student nextStudent() { student = studentList.get(position); position++; return student; } @Override public boolean isLastStudent() { return position < studentList.size(); } }
-
抽象聚合接口StudentAggregate
/** * @description: 学生集合接口,定义存储Student类的接口 * @Date: 2021/10/14 16:15 */ public interface StudentAggregate { //业务方法 void addStudent(Student student); //业务方法 void removeStudent(Student student); //获取迭代器方法 AggregateIterator getStudentIterator(); }
-
具体的聚合实现类
/** * @description: 学生集合接口实现类 * @Date: 2021/10/14 16:16 */ public class StudentAggregateImpl implements StudentAggregate{ private List<Student> studentList; public StudentAggregateImpl(){ this.studentList = new ArrayList<Student>(); } //实现业务方法 @Override public void addStudent(Student student) { studentList.add(student); } //实现业务方法 @Override public void removeStudent(Student student) { studentList.remove(student); } //返回一个迭代器实例 @Override public AggregateIterator getStudentIterator() { return new StudentAggregateIteratorImpl(studentList); } }
-
存储元素Student类
/** * @description: 学生类 * @Date: 2021/10/14 16:13 */ public class Student { private String name; public Student(String name){ this.name = name; } public String getName(){ return this.name; } }
在创建以上5项内容之后,就可以使用StudentAggregateImpl对象存储多个Student对象。在调用时,调用StudentAggregateImpl对象的getStudentIterator()方法获取对应的迭代器对象。在使用迭代器对象的方法按顺序访问StudentAggregateImpl对象中的Student对象。
public class AllTest {
public static void main(String[] args) {
StudentAggregateImpl studentAggregate = new StudentAggregateImpl();
//存储Student对象
studentAggregate.addStudent(new Student("1"));
studentAggregate.addStudent(new Student("2"));
studentAggregate.addStudent(new Student("3"));
//获取StudentAggregateImpl的迭代器
AggregateIterator studentIterator = studentAggregate.getStudentIterator();
//遍历StudentAggregateImpl对象中的元素
while (studentIterator.isLastStudent()){
System.out.println(studentIterator.nextStudent().getName());
}
}
}
源码分析
参看详解java集合框架中的迭代器模式(Iterator接口 Iterable接口)
适用场景
顾名思义,迭代器用于迭代聚合数据类型,java中的聚合数据类型实际是指集合框架。集合框架中广泛使用迭代器模式,具体参看另一篇文章详解java集合框架中的迭代器模式(Iterator接口 Iterable接口)。
由于java的集合框架提供的功能基本满足日常开发需要,一般不会在设计新的容器类,也就不会实现对应的迭代器。若需要自定义实现聚合类型,则同样需要提供该集合的迭代器。
参考资料
-
headfirst设计模式(中文版)