一、定义
迭代器模式是一种行为型设计模式,它提供一种统一的方式遍历聚合对象(如集合、列表、树等)中的元素,同时不暴露聚合对象的内部实现细节。其核心是将 "遍历逻辑" 与 "聚合对象" 解耦,使客户端能以一致的代码操作不同类型的聚合,无需关心聚合的底层数据结构(如数组、链表、哈希表等)。
二、优缺点分析
优点
1、解耦遍历与聚合:客户端无需了解聚合的内部结构(如数组用索引、链表用指针),只需通过迭代器的通用方法遍历,降低代码耦合度。
2、统一遍历接口:不同聚合的遍历逻辑被封装在各自的迭代器中,客户端可通过相同代码操作不同聚合(如用同一方法遍历数组和链表)。
3、符合开闭原则:新增聚合类型时,只需实现对应的迭代器,无需修改现有客户端代码;也可新增迭代器实现多种遍历方式(如正序、逆序)。
4、单一职责原则:聚合仅负责存储数据,遍历逻辑交给迭代器,职责更清晰。
缺点
1、类数量增加:每种聚合通常需要对应一个迭代器,可能导致系统中类的数量增多。
2、遍历效率损耗:对简单聚合(如数组),直接通过索引遍历可能比迭代器更高效(但灵活性通常能弥补这一差异)。
3、迭代中修改聚合的风险:若遍历过程中增删聚合元素,可能导致迭代器状态混乱(需额外处理,如 C# 的InvalidOperationException)。
三、应用场景
1、需要统一遍历不同聚合:当系统中有多种聚合类型(如数组、链表、字典),且希望用相同代码遍历它们时(如框架中的集合类)。
2、不希望暴露聚合内部结构:当聚合的实现复杂(如树、图),需隐藏内部细节(如数据库查询结果集的遍历)。
3、需要多种遍历方式:同一聚合需支持正序、逆序、过滤等多种遍历逻辑(如双向迭代器、条件迭代器)。
4、框架或工具类开发:开发通用组件(如集合库、ORM 框架)时,迭代器是核心组件(如 C# 的IEnumerator)。
四、关键点总结
1、核心思想:将遍历逻辑从聚合中分离,通过迭代器封装遍历细节,实现 "遍历与聚合" 的解耦。
2、核心角色:
- 抽象迭代器(如IIterator):定义遍历接口(HasNext、Next)。
- 具体迭代器(如BookshelfIterator):实现具体聚合的遍历逻辑。
- 抽象聚合(如IAggregate):定义创建迭代器的方法。
- 具体聚合(如Bookshelf):存储元素并返回对应迭代器。
3、C# 特性:.NET 框架的IEnumerator和IEnumerable接口是迭代器模式的典型实现,foreach循环底层依赖这两个接口,简化了迭代器的使用。
4、设计原则:符合开闭原则(新增聚合 / 迭代器无需修改客户端)和单一职责原则(聚合与迭代器各司其职)。
五、C# 代码示例
以 "遍历两种图书集合(书架、电子书库)" 为例,演示迭代器模式的实现。
1、抽象迭代器(IIterator)
定义遍历的通用方法:
csharp
// 抽象迭代器接口
public interface IBookIterator
{
bool HasNext(); // 判断是否有下一个元素
Book Next(); // 获取下一个元素
}
2、抽象聚合(IAggregate)
定义创建迭代器的方法:
csharp
// 抽象聚合接口
public interface IBookAggregate
{
void AddBook(Book book); // 添加图书
IBookIterator CreateIterator(); // 创建迭代器
}
3、聚合元素(Book)
聚合中存储的具体元素:
csharp
// 图书类(聚合中的元素)
public class Book
{
public string Name { get; } // 书名
public string Author { get; } // 作者
public Book(string name, string author)
{
Name = name;
Author = author;
}
}
4、具体聚合与迭代器
4.1、书架(数组实现)
csharp
// 具体聚合:书架(数组存储)
public class Bookshelf : IBookAggregate
{
private Book[] _books; // 数组存储图书
private int _count; // 当前图书数量
public Bookshelf(int capacity)
{
_books = new Book[capacity];
_count = 0;
}
public void AddBook(Book book)
{
if (_count < _books.Length)
_books[_count++] = book;
else
throw new InvalidOperationException("书架已满");
}
// 返回书架的迭代器
public IBookIterator CreateIterator()
{
return new BookshelfIterator(this);
}
// 供迭代器访问内部元素的方法(隐藏数组细节)
internal Book GetBookAt(int index) => _books[index];
internal int GetCount() => _count;
// 具体迭代器:适配数组遍历
private class BookshelfIterator : IBookIterator
{
private readonly Bookshelf _bookshelf;
private int _currentIndex; // 当前索引
public BookshelfIterator(Bookshelf bookshelf)
{
_bookshelf = bookshelf;
_currentIndex = 0; // 从0开始
}
public bool HasNext() => _currentIndex < _bookshelf.GetCount();
public Book Next()
{
if (!HasNext())
throw new InvalidOperationException("没有更多图书");
return _bookshelf.GetBookAt(_currentIndex++);
}
}
}
4.2、电子书库(链表实现)
csharp
// 具体聚合:电子书库(链表存储)
public class EBookLibrary : IBookAggregate
{
// 链表节点
private class Node
{
public Book Book { get; }
public Node Next { get; set; }
public Node(Book book)
{
Book = book;
Next = null;
}
}
private Node _head; // 头节点
private int _count; // 图书数量
public EBookLibrary()
{
_head = null;
_count = 0;
}
public void AddBook(Book book)
{
Node newNode = new Node(book);
if (_head == null)
_head = newNode;
else
{
Node current = _head;
while (current.Next != null)
current = current.Next;
current.Next = newNode;
}
_count++;
}
// 返回电子书库的迭代器
public IBookIterator CreateIterator()
{
return new EBookLibraryIterator(this);
}
// 供迭代器访问头节点
internal Node GetHead() => _head;
// 具体迭代器:适配链表遍历
private class EBookLibraryIterator : IBookIterator
{
private readonly EBookLibrary _library;
private Node _currentNode; // 当前节点
public EBookLibraryIterator(EBookLibrary library)
{
_library = library;
_currentNode = _library.GetHead(); // 从头节点开始
}
public bool HasNext() => _currentNode != null;
public Book Next()
{
if (!HasNext())
throw new InvalidOperationException("没有更多电子书");
Book book = _currentNode.Book;
_currentNode = _currentNode.Next; // 移动到下一个节点
return book;
}
}
}
5、客户端调用
csharp
class Client
{
static void Main(string[] args)
{
// 1. 书架(数组实现)
IBookAggregate bookshelf = new Bookshelf(3);
bookshelf.AddBook(new Book("《设计模式》", "Erich Gamma"));
bookshelf.AddBook(new Book("《C#编程指南》", "微软"));
bookshelf.AddBook(new Book("《算法导论》", "Thomas H. Cormen"));
// 2. 电子书库(链表实现)
IBookAggregate ebookLib = new EBookLibrary();
ebookLib.AddBook(new Book("《深入理解C#》", "Jon Skeet"));
ebookLib.AddBook(new Book("《.NET框架设计》", "Jeffrey Richter"));
// 3. 统一遍历
Console.WriteLine("=== 遍历书架 ===");
TraverseBooks(bookshelf);
Console.WriteLine("\n=== 遍历电子书库 ===");
TraverseBooks(ebookLib);
}
// 通用遍历方法(依赖抽象,不依赖具体实现)
static void TraverseBooks(IBookAggregate aggregate)
{
IBookIterator iterator = aggregate.CreateIterator();
while (iterator.HasNext())
{
Book book = iterator.Next();
Console.WriteLine($"书名:{book.Name},作者:{book.Author}");
}
}
}
输出结果
csharp
=== 遍历书架 ===
书名:《设计模式》,作者:Erich Gamma
书名:《C#编程指南》,作者:微软
书名:《算法导论》,作者:Thomas H. Cormen
=== 遍历电子书库 ===
书名:《深入理解C#》,作者:Jon Skeet
书名:《.NET框架设计》,作者:Jeffrey Richter
迭代器模式通过封装遍历逻辑,让客户端可以忽略聚合的内部细节,是框架设计中简化集合操作的核心模式。
