在开发中,我们经常需要遍历某些集合,例如遍历购物车中的商品、遍历数据库返回的结果、遍历某个目录下的所有文件等。如果不使用统一的遍历方式,我们就得手动维护下标或者暴露集合的内部结构,不仅繁琐,还容易出错。
那么有没有一种方法,可以在不暴露集合内部结构的前提下,提供一种统一的遍历机制?
答案就是使用 迭代器模式(Iterator)。
什么是迭代器模式?
迭代器模式 是一种行为型设计模式,它提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
你可以把它理解为“遍历器”或者“游标”,只负责顺序地访问元素,让使用者专注于“遍历”,而不是集合内部的实现细节。
迭代器模式的结构组成
迭代器模式的核心由四部分组成:
- Iterator(抽象迭代器):定义遍历集合元素的方法,如
hasNext()、next()。 - ConcreteIterator(具体迭代器):实现迭代器接口,记录当前遍历位置。
- Aggregate(抽象聚合):定义获取迭代器的方法。
- ConcreteAggregate(具体聚合):实现聚合接口,返回一个具体迭代器实例。
实际场景举例
我们以一个“书架(BookShelf)”的例子来理解。书架上可以放很多本书,我们要遍历每一本书的信息。这个过程不应该暴露书架底层的存储方式(比如是数组还是 List),只需要关注怎么一一获取书。
代码实现
1. 抽象迭代器接口 Iterator
public interface Iterator {
boolean hasNext(); // 是否还有下一个元素
Object next(); // 获取下一个元素
}
2. 聚合接口 BookCollection
public interface BookCollection {
Iterator getIterator(); // 获取一个迭代器
}
3. 具体聚合类 BookShelf
import java.util.ArrayList;
import java.util.List;
public class BookShelf implements BookCollection {
private List<String> books = new ArrayList<>();
public void addBook(String name) {
books.add(name);
}
public String getBookAt(int index) {
return books.get(index);
}
public int getSize() {
return books.size();
}
@Override
public Iterator getIterator() {
return new BookShelfIterator(this);
}
}
4. 具体迭代器类 BookShelfIterator
public class BookShelfIterator implements Iterator {
private BookShelf bookShelf;
private int index = 0;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
}
@Override
public boolean hasNext() {
return index < bookShelf.getSize();
}
@Override
public Object next() {
return bookShelf.getBookAt(index++);
}
}
5. 客户端调用
public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf();
bookShelf.addBook("设计模式");
bookShelf.addBook("重构");
bookShelf.addBook("Java编程思想");
Iterator iterator = bookShelf.getIterator();
while (iterator.hasNext()) {
System.out.println("书籍:" + iterator.next());
}
}
}
输出结果
书籍:设计模式
书籍:重构
书籍:Java编程思想
小结
在本节中,我们通过书架的例子学习了迭代器模式。它将集合内部结构与遍历逻辑进行了解耦,让我们可以优雅、安全地遍历集合元素。
这个设计思想与 Java 的 Iterator 接口、ListIterator、Enumeration 非常类似。
迭代器模式的优缺点
优点
- 解耦聚合对象和遍历操作,符合单一职责原则。
- 支持多种不同方式的遍历,如从前往后、从后往前、按条件过滤等。
- 统一接口,让使用者不必关心集合的内部结构。
缺点
- 每增加一个新的集合类型或遍历方式,就可能需要额外实现一个迭代器,导致类数量增多。
- 对于大数据量或并发修改的集合,可能涉及额外的性能和一致性处理。
典型应用场景
- Java 集合类中的迭代器(Iterator、ListIterator)
- 数据库结果集遍历(ResultSet)
- 内部数据结构不可公开但需要对外遍历的场景