迭代器模式
引言
在软件系统中,当需要统一访问不同结构的集合对象(如数组、链表、树形结构)时,直接暴露内部存储逻辑会导致代码重复和强耦合。迭代器模式通过提供标准遍历接口,实现集合元素的按需访问,成为数据遍历的"通用遥控器"。
诞生背景
GoF在《设计模式》中提出迭代器模式,解决三大痛点:
- 遍历方式暴露:客户端需了解集合内部结构(如链表
next指针) - 遍历逻辑耦合:相同遍历逻辑重复出现在多个客户端
- 多集合支持困难:无法用统一方式处理数组/树/图等不同结构
演进过程
- GoF基础(1994):确立核心角色(迭代器接口、具体迭代器)
- 语言级集成:Java的
java.util.Iterator/PHP的Iterator接口成为标准 - 现代演进:
- 函数式编程引入惰性迭代(如Java Stream API)
- 生成器实现(PHP的
yield关键字)
核心概念
- 迭代器(Iterator)
- 定义访问元素的接口(
hasNext(),next())
- 定义访问元素的接口(
- 具体迭代器(ConcreteIterator)
- 实现特定集合的遍历逻辑
- 聚合对象(Aggregate)
- 定义创建迭代器的方法(
createIterator())
- 定义创建迭代器的方法(
- 客户端(Client)
- 通过迭代器接口访问元素,不依赖集合实现
通用实现
Java 实现
java
// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
}
// 聚合对象接口
interface Aggregate<T> {
Iterator<T> createIterator();
}
// 具体聚合对象:数组集合
class ArrayCollection<T> implements Aggregate<T> {
private T[] items;
public ArrayCollection(T[] items) {
this.items = items;
}
@Override
public Iterator<T> createIterator() {
return new ArrayIterator<>(items);
}
}
// 具体迭代器:数组迭代器
class ArrayIterator<T> implements Iterator<T> {
private T[] items;
private int position = 0;
public ArrayIterator(T[] items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.length;
}
@Override
public T next() {
return items[position++];
}
}
// 客户端
public class Client {
public static void main(String[] args) {
String[] data = {"A", "B", "C"};
Aggregate<String> collection = new ArrayCollection<>(data);
Iterator<String> it = collection.createIterator();
while(it.hasNext()) {
System.out.println(it.next()); // A → B → C
}
}
}PHP 实现
php
// 迭代器接口
interface IteratorInterface {
public function hasNext(): bool;
public function next();
}
// 聚合对象接口
interface Aggregate {
public function createIterator(): IteratorInterface;
}
// 具体聚合对象:链表集合
class LinkedList implements Aggregate {
private array $items = [];
public function addItem($item): void {
$this->items[] = $item;
}
public function createIterator(): IteratorInterface {
return new LinkedListIterator($this->items);
}
}
// 具体迭代器:链表迭代器
class LinkedListIterator implements IteratorInterface {
private array $items;
private int $position = 0;
public function __construct(array $items) {
$this->items = $items;
}
public function hasNext(): bool {
return $this->position < count($this->items);
}
public function next() {
return $this->items[$this->position++];
}
}
// 客户端
$list = new LinkedList();
$list->addItem("X");
$list->addItem("Y");
$iterator = $list->createIterator();
while($iterator->hasNext()) {
echo $iterator->next() . "\n"; // X → Y
}应用场景
- 统一遍历接口:处理不同结构的集合(数组/树/图)
- 封装集合实现:隐藏集合内部存储细节
- 并行遍历:支持同一集合的多个独立遍历
- 延迟加载:按需获取元素(如数据库分页查询)
案例:图书馆目录系统
Java 实现
java
// 图书类
class Book {
private String title;
public Book(String title) { this.title = title; }
public String getTitle() { return title; }
}
// 图书目录(树形结构)
class BookCatalog implements Aggregate<Book> {
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
@Override
public Iterator<Book> createIterator() {
return new BookIterator(books);
}
}
// 图书迭代器(支持过滤)
class BookIterator implements Iterator<Book> {
private List<Book> books;
private int index = 0;
private String filter;
public BookIterator(List<Book> books) {
this(books, null);
}
public BookIterator(List<Book> books, String filter) {
this.books = books;
this.filter = filter;
}
@Override
public boolean hasNext() {
while (index < books.size()) {
if (filter == null || books.get(index).getTitle().contains(filter))
return true;
index++;
}
return false;
}
@Override
public Book next() {
return books.get(index++);
}
}
// 客户端:查找含"Design"的书
BookCatalog catalog = new BookCatalog();
catalog.addBook(new Book("Design Patterns"));
catalog.addBook(new Book("Clean Code"));
Iterator<Book> it = new BookIterator(catalog, "Design");
while(it.hasNext()) {
System.out.println(it.next().getTitle()); // 输出: Design Patterns
}PHP 实现
php
// 图书类
class Book {
private string $title;
public function __construct(string $title) {
$this->title = $title;
}
public function getTitle(): string {
return $this->title;
}
}
// 图书目录(组合结构)
class BookCatalog implements Aggregate {
private array $categories = [];
public function addCategory(string $name, array $books): void {
$this->categories[$name] = $books;
}
public function createIterator(): IteratorInterface {
return new CategoryIterator($this->categories);
}
}
// 分类迭代器(深度优先遍历)
class CategoryIterator implements IteratorInterface {
private array $categories;
private array $stack = [];
public function __construct(array $categories) {
$this->categories = $categories;
$this->stack = array_reverse($categories);
}
public function hasNext(): bool {
return !empty($this->stack);
}
public function next() {
$current = array_pop($this->stack);
if (is_array($current)) {
$this->stack = array_merge(
$this->stack,
array_reverse($current)
);
return $this->next();
}
return $current;
}
}
// 客户端
$catalog = new BookCatalog();
$catalog->addCategory("Design", [new Book("Patterns"), new Book("Architecture")]);
$catalog->addCategory("Programming", [new Book("PHP 8"), new Book("Java 17")]);
$iterator = $catalog->createIterator();
while($iterator->hasNext()) {
$book = $iterator->next();
echo $book->getTitle() . "\n";
// 输出: Patterns → Architecture → PHP 8 → Java 17
}优点
- 解耦遍历:客户端与集合实现分离
- 多态迭代:相同接口处理不同集合结构
- 并行遍历:支持多个独立的遍历过程
- 延迟执行:按需获取元素节省资源
缺点
- 性能开销:迭代器对象创建增加内存消耗
- 访问限制:难以直接访问特定位置元素
- 修改风险:遍历中修改集合可能导致异常
扩展
- 过滤迭代器:
java
class FilterIterator implements Iterator<T> {
private Iterator<T> source;
private Predicate<T> filter;
// 实现条件过滤的hasNext/next
}- 并发迭代器:
- 使用快照机制防止
ConcurrentModificationException
- 使用快照机制防止
- 组合迭代器:
- 嵌套迭代器处理树形结构(如文件系统遍历)
模式协作
- 与组合模式:迭代树形结构(如
DirectoryIterator) - 与工厂方法:聚合对象使用工厂创建迭代器
- 与备忘录:实现迭代状态保存/恢复
延伸思考
- 语言级支持:
- Java的
Iterable接口+增强for循环 - PHP的
foreach背后自动调用Iterator接口
- 函数式编程:
- Java Stream API的
filter()/map()即链式迭代器
- 无限序列:
- 生成器实现斐波那契数列迭代
php
function fibonacci() {
$a = 0; $b = 1;
while(true) {
yield $a;
[$a, $b] = [$b, $a + $b];
}
}总结
迭代器模式是集合访问的抽象层,通过标准化遍历接口,实现"透明访问集合元素"的目标。其核心价值在于:遍历逻辑与数据结构的解耦和统一访问协议的建立。从简单数组到复杂树形结构,迭代器模式为数据遍历提供了优雅的通用解决方案。