迭代器模式(Iterator Pattern)是一种经典的行为型设计模式,其核心目标是提供一种标准化方式顺序访问聚合对象中的各个元素,同时不暴露该对象的内部存储结构。它通过将遍历逻辑与集合本身解耦,让集合类专注于数据的存储与管理,迭代器类专注于遍历行为的实现,大幅提升代码的灵活性、可维护性与可扩展性,是处理集合遍历场景的核心设计范式。
迭代器模式的核心价值在于“分离遍历与存储”,它屏蔽了不同集合(如数组、链表、哈希表)的底层实现差异,为外部提供统一的遍历接口,使得调用者无需关心集合的内部结构,只需通过迭代器即可完成元素的遍历,完美契合“单一职责原则”与“开闭原则”。
一、迭代器模式的核心结构
迭代器模式的结构清晰,角色分工明确,核心由四个角色构成,各角色协同工作,共同实现“解耦遍历逻辑与集合存储”的核心目标,确保遍历行为的标准化与集合的封装性:
1.1 抽象迭代器(Iterator)
定义遍历聚合对象的通用接口,是所有具体迭代器的行为契约。通常包含两个核心方法:HasNext()(判断当前位置是否还有下一个元素,返回布尔值)和Next()(获取当前位置的下一个元素,并将遍历指针移动到下一位),部分场景可扩展Reset()(重置遍历指针)、Remove()(移除当前元素)等方法。
1.2 具体迭代器(Concrete Iterator)
实现抽象迭代器接口,是迭代器模式的核心执行类。它内部持有对应具体聚合对象的引用,维护当前遍历的位置指针,负责完成实际的遍历逻辑,同时处理迭代边界(如越界判断),确保遍历的安全性。
1.3 抽象聚合类(Aggregate)
定义聚合对象的通用接口,声明集合的核心行为(如添加、删除元素),并提供一个创建迭代器的抽象方法(如CreateIterator())。抽象聚合类的核心作用是规范具体聚合类的行为,同时为外部提供获取迭代器的统一入口。
1.4 具体聚合类(Concrete Aggregate)
实现抽象聚合类的接口,是被遍历的目标集合,负责存储具体的元素数据(如数组、链表等底层结构)。它会返回一个与自身匹配的具体迭代器实例,将遍历逻辑委托给迭代器,自身仅专注于数据的存储与管理。
核心逻辑链路:客户端 → 实例化具体聚合类(存储数据) → 调用聚合类的CreateIterator()方法获取具体迭代器 → 通过迭代器的HasNext()和Next()方法遍历元素 → 完成遍历。整个过程中,客户端无需关注集合的内部结构,仅与迭代器接口交互。
二、多语言实现迭代器模式
为便于开发者落地实践,本文以“字符串集合遍历”为经典案例,实现多语言版本的迭代器模式,覆盖面向对象语言、动态语言、面向过程语言及Go语言的特色实现。所有实现均保证完整可运行,贴合各语言设计理念,补充规范注释、异常处理和边界判断,兼顾实用性与可读性,同时体现各语言对迭代器模式的适配方式。
2.1 C# 实现(依托内置接口,贴合语言特性)
C# 语言内置了IEnumerator(抽象迭代器)和IEnumerable(抽象聚合类)接口,天然适配迭代器模式,开发者可直接复用内置接口实现,无需自定义抽象层,代码简洁且符合.NET框架规范,适配企业级系统开发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| using System; using System.Collections;
public class StringIterator : IEnumerator { private readonly string[] _items; private int _position = -1;
public StringIterator(string[] items) { _items = items ?? throw new ArgumentNullException(nameof(items), "遍历的集合不可为null"); }
public object Current { get { if (_position < 0 || _position >= _items.Length) { throw new InvalidOperationException("迭代器位置非法,无法获取当前元素"); } return _items[_position]; } }
public bool MoveNext() { _position++; return _position < _items.Length; }
public void Reset() { _position = -1; } }
public class StringCollection : IEnumerable { private readonly string[] _items;
public StringCollection(string[] items) { _items = items ?? throw new ArgumentNullException(nameof(items), "集合元素不可为null"); }
public IEnumerator GetEnumerator() { return new StringIterator(_items); } }
class Program { static void Main() { try { var collection = new StringCollection(new[] { "C#", "迭代器模式", "设计模式" }); Console.WriteLine("C# 迭代器遍历结果:"); foreach (var item in collection) { Console.WriteLine(item); } } catch (Exception ex) { Console.WriteLine($"遍历异常:{ex.Message}"); } } }
|
2.2 Python 实现(依托迭代器协议,简洁高效)
Python 不强制要求定义抽象接口,而是通过“迭代器协议”(实现__iter__和__next__方法)实现迭代器功能,语法简洁灵活,无需繁琐的接口声明,依托GC自动管理内存,适配快速开发、脚本开发及轻量级项目场景,完美贴合Python“简洁实用”的设计理念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class StringIterator: def __init__(self, items): """初始化迭代器""" self._items = items if items is not None else [] self._index = 0 def __iter__(self): """迭代器协议要求:返回自身,支持for-in遍历""" return self def __next__(self): """迭代器协议要求:获取下一个元素,无元素时抛出StopIteration终止遍历""" if self._index < len(self._items): result = self._items[self._index] self._index += 1 return result raise StopIteration("迭代已结束,无更多元素")
class StringCollection: def __init__(self, items): """初始化字符串集合""" self._items = items if items is not None else [] def __iter__(self): """返回具体迭代器实例,供外部遍历""" return StringIterator(self._items)
if __name__ == "__main__": try: collection = StringCollection(["Python", "迭代器模式", "设计模式"]) print("Python 迭代器遍历结果:") for item in collection: print(item) except StopIteration as e: print(f"迭代异常:{e}") except Exception as e: print(f"其他异常:{str(e)}")
|
2.3 Go 实现(接口+结构体,轻量化实现)
Go 语言无类和继承概念,核心遵循“组合优于继承”的设计哲学,通过接口定义迭代器和聚合类的契约,结构体实现具体的迭代器和聚合逻辑,代码极简、高效,贴合Go语言“简洁、务实、高性能”的设计理念,适配高并发、高性能的后端开发场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| package main
import ( "fmt" )
type Iterator interface { HasNext() bool Next() string Reset() }
type StringIterator struct { items []string index int }
func NewStringIterator(items []string) *StringIterator { if items == nil { items = make([]string, 0) } return &StringIterator{ items: items, index: 0, } }
func (it *StringIterator) HasNext() bool { return it.index < len(it.items) }
func (it *StringIterator) Next() string { if it.HasNext() { item := it.items[it.index] it.index++ return item } fmt.Println("迭代已结束,无更多元素") return "" }
func (it *StringIterator) Reset() { it.index = 0 }
type Aggregate interface { CreateIterator() Iterator }
type StringCollection struct { items []string }
func NewStringCollection(items []string) *StringCollection { if items == nil { items = make([]string, 0) } return &StringCollection{ items: items, } }
func (c *StringCollection) CreateIterator() Iterator { return NewStringIterator(c.items) }
func main() { collection := NewStringCollection([]string{"Go", "迭代器模式", "设计模式"}) iterator := collection.CreateIterator()
fmt.Println("Go 迭代器遍历结果:") for iterator.HasNext() { fmt.Println(iterator.Next()) }
iterator.Reset() fmt.Println("Go 迭代器重置后遍历结果:") for iterator.HasNext() { fmt.Println(iterator.Next()) } }
|
2.4 C++ 实现(抽象类+模板,通用化设计)
C++ 作为经典面向对象语言,通过抽象类(纯虚函数)定义迭代器和聚合类的接口,结合模板机制实现通用化设计,支持多种数据类型的遍历,兼顾灵活性与高性能,需手动管理内存,适配底层开发、高频调用场景,是底层系统、高性能应用的优选实现方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include <iostream> #include <vector> #include <string> #include <stdexcept> using namespace std;
template <typename T> class Iterator { public: virtual ~Iterator() = default; virtual bool HasNext() = 0; virtual T Next() = 0; virtual void Reset() = 0; };
template <typename T> class ConcreteIterator : public Iterator<T> { private: vector<T> items; int index; public: ConcreteIterator(const vector<T>& items) : items(items), index(0) {}
bool HasNext() override { return index < items.size(); }
T Next() override { if (HasNext()) { return items[index++]; } throw out_of_range("迭代器越界,无更多元素"); }
void Reset() override { index = 0; } };
template <typename T> class Aggregate { public: virtual ~Aggregate() = default; virtual Iterator<T>* CreateIterator() = 0; virtual void Add(const T& item) = 0; };
template <typename T> class ConcreteAggregate : public Aggregate<T> { private: vector<T> items; public: void Add(const T& item) override { items.push_back(item); }
Iterator<T>* CreateIterator() override { return new ConcreteIterator<T>(items); } };
int main() { try { ConcreteAggregate<string> collection; collection.Add("C++"); collection.Add("迭代器模式"); collection.Add("设计模式");
Iterator<string>* iterator = collection.CreateIterator(); cout << "C++ 迭代器遍历结果:" << endl;
while (iterator->HasNext()) { cout << iterator->Next() << endl; }
iterator->Reset(); cout << "C++ 迭代器重置后遍历结果:" << endl; while (iterator->HasNext()) { cout << iterator->Next() << endl; }
delete iterator; } catch (const out_of_range& e) { cout << "迭代异常:" << e.what() << endl; } catch (const exception& e) { cout << "其他异常:" << e.what() << endl; }
return 0; }
|
2.5 纯C语言实现(结构体+函数指针,模拟实现)
纯C语言无面向对象特性,无类和多态,通过“结构体封装数据+函数指针封装行为”,手动模拟迭代器模式的核心逻辑。用结构体封装聚合对象和迭代器的属性,用函数指针模拟抽象接口的方法,需手动管理内存,代码虽略显冗余,但底层可控性强,适配嵌入式、底层开发等资源受限场景,完美还原“遍历与存储解耦”的核心思想。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| #include <stdio.h> #include <stdlib.h> #include <string.h>
#define MAX_STR_LEN 32
typedef struct { char** items; int length; int index; int (*HasNext)(void*); char* (*Next)(void*); void (*Reset)(void*); } Iterator;
int has_next(void* iterator) { if (iterator == NULL) { printf("迭代器实例为空,无法判断是否有下一个元素\n"); return 0; } Iterator* it = (Iterator*)iterator; return it->index < it->length ? 1 : 0; }
char* next(void* iterator) { if (iterator == NULL) { printf("迭代器实例为空,无法获取元素\n"); return NULL; } Iterator* it = (Iterator*)iterator; if (has_next(it)) { char* item = (char*)malloc(MAX_STR_LEN * sizeof(char)); if (item == NULL) { printf("内存分配失败,无法获取元素\n"); return NULL; } strncpy(item, it->items[it->index], MAX_STR_LEN - 1); item[MAX_STR_LEN - 1] = '\0'; it->index++; return item; } printf("迭代已结束,无更多元素\n"); return NULL; }
void reset(void* iterator) { if (iterator == NULL) { printf("迭代器实例为空,无法重置\n"); return; } Iterator* it = (Iterator*)iterator; it->index = 0; }
typedef struct { char** items; int length; Iterator* (*CreateIterator)(void*); } Aggregate;
Iterator* create_iterator(void* aggregate) { if (aggregate == NULL) { printf("聚合对象为空,无法创建迭代器\n"); return NULL; } Aggregate* agg = (Aggregate*)aggregate; Iterator* it = (Iterator*)malloc(sizeof(Iterator)); if (it == NULL) { printf("内存分配失败,无法创建迭代器\n"); return NULL; } it->items = agg->items; it->length = agg->length; it->index = 0; it->HasNext = has_next; it->Next = next; it->Reset = reset; return it; }
void iterator_destroy(Iterator* it) { if (it != NULL) { free(it); it = NULL; } }
int main() { char* items[] = {"C语言", "迭代器模式", "设计模式"}; int len = sizeof(items) / sizeof(char*);
Aggregate aggregate; aggregate.items = items; aggregate.length = len; aggregate.CreateIterator = create_iterator;
Iterator* iterator = aggregate.CreateIterator(&aggregate); if (iterator == NULL) { return -1; }
printf("C语言 迭代器遍历结果:\n"); char* item = NULL; while (iterator->HasNext(iterator)) { item = iterator->Next(iterator); if (item != NULL) { printf("%s\n", item); free(item); item = NULL; } }
iterator->Reset(iterator); printf("C语言 迭代器重置后遍历结果:\n"); while (iterator->HasNext(iterator)) { item = iterator->Next(iterator); if (item != NULL) { printf("%s\n", item); free(item); item = NULL; } }
iterator_destroy(iterator); return 0; }
|
三、迭代器模式的优缺点
迭代器模式的核心价值是“解耦遍历逻辑与集合存储,提供统一遍历接口”,其优缺点均围绕这一核心展开。在实际开发中,需结合集合的复杂度、遍历场景的需求和性能要求,权衡使用,避免过度设计或滥用,确保既发挥其核心优势,又规避潜在问题。
3.1 核心优点
解耦遍历与集合,符合单一职责原则:集合类专注于数据的存储与管理,迭代器类专注于遍历逻辑的实现,两者职责分离,降低代码耦合度,便于后期维护和迭代。
统一遍历接口,屏蔽底层差异:无论集合的底层存储结构(数组、链表、哈希表、树等)如何,外部都通过统一的迭代器接口遍历元素,调用者无需关心集合的内部实现,降低使用成本,提升代码的通用性。
支持多态遍历,扩展灵活:可针对同一集合实现多种迭代器(如正序遍历、逆序遍历、过滤遍历、深度优先遍历),无需修改集合本身,新增遍历逻辑只需新增迭代器,符合“开闭原则”。
简化集合扩展,提升系统可维护性:新增集合类型时,只需实现对应的迭代器,无需修改已有遍历代码,降低扩展成本;同时,遍历逻辑的修改仅需调整迭代器,不影响集合和调用者。
保护集合封装性:迭代器仅暴露遍历接口,不暴露集合的内部存储结构和操作细节,避免外部直接操作集合内部数据,提升代码的安全性和封装性。
3.2 主要缺点
增加代码复杂度,冗余度提升:对于简单集合(如小型数组),直接使用下标遍历或语言内置遍历方式即可,引入迭代器会增加额外的类/结构体、接口和方法定义,导致代码冗余,增加开发和维护成本。
存在轻微性能开销:相比直接遍历集合(如数组下标访问),迭代器的方法调用(如HasNext()、Next())会带来轻微的运行时开销,对于高频遍历、低延迟要求的场景(如底层算法、高频数据处理),可能影响性能。
双向迭代/随机访问实现复杂:基础迭代器仅支持单向顺序遍历,若需实现双向迭代(向前/向后遍历)或随机访问(直接访问指定位置元素),需扩展迭代器接口,增加设计复杂度和实现成本。
多线程场景下需额外处理同步:在多线程并发遍历集合时,若集合发生修改(添加、删除元素),迭代器可能出现遍历异常(如 ConcurrentModificationException),需额外添加同步机制,增加代码复杂度。
四、迭代器模式的使用场景
迭代器模式的核心适用场景是“需要统一遍历接口、隐藏集合内部结构,或需要灵活扩展遍历逻辑”的业务场景。以下结合具体场景及典型实战案例,帮助开发者快速判断是否适用,实现精准落地,避免滥用或错用。
4.1 核心适用场景
隐藏集合内部结构的场景:当需要对外屏蔽集合的底层实现(如自定义容器、复杂数据结构、第三方集合库),仅暴露遍历能力,避免外部依赖集合的内部结构时,如框架级别的集合组件、自定义数据容器。
统一多集合遍历方式的场景:系统中存在多种集合类型(数组、链表、哈希表、树等),需为调用者提供一致的遍历接口,降低调用者的使用成本,如通用工具类、集合框架(如C#的ICollection、Java的Collection)。
自定义遍历逻辑的场景:需要实现特殊遍历规则(如过滤元素、逆序遍历、深度优先/广度优先遍历树/图结构、分页遍历),且遍历逻辑可能频繁变化时,如数据筛选工具、树形结构遍历、分页查询结果遍历。
跨语言/框架的集合操作场景:在多语言协作或通用框架中,需标准化集合遍历行为,确保不同语言、不同组件的遍历接口一致,如跨语言RPC框架中的集合传输、通用数据处理组件。
集合扩展频繁的场景:系统中频繁新增集合类型,且需要保证遍历接口的一致性,无需修改已有遍历代码,如插件化系统中的集合扩展、动态数据结构的遍历。
4.2 典型实战案例
编程语言内置集合框架:如C#的IEnumerable/IEnumerator、Java的Iterator/Iterable、C++的STL迭代器、Python的迭代器协议,均是迭代器模式的经典实现,为开发者提供统一的集合遍历接口。
数据库查询结果集遍历:如JDBC的ResultSet、ORM框架(MyBatis、EF Core)的查询结果迭代器,将数据库查询结果封装为集合,通过迭代器逐行遍历,屏蔽数据库底层存储差异。
树形结构/图结构遍历:如二叉树的前序、中序、后序遍历,图的深度优先(DFS)、广度优先(BFS)遍历,通过自定义迭代器实现不同的遍历逻辑,无需修改树/图的核心结构。
分页数据遍历:如电商平台的商品列表分页、后台系统的订单分页查询,通过迭代器封装分页逻辑,调用者只需通过迭代器获取下一页数据,无需关心分页的实现细节。
自定义容器开发:如开发自定义的缓存容器、队列、栈等数据结构,通过迭代器暴露遍历能力,隐藏容器的内部存储结构(如数组、链表),提升容器的封装性和可扩展性。
五、总结
迭代器模式的核心是“分离遍历逻辑与数据存储,提供统一的遍历接口”,它是“单一职责原则”和“开闭原则”的典型落地方式,通过将遍历行为抽离为独立的迭代器,让集合专注于数据管理,迭代器专注于遍历实现,大幅提升代码的灵活性、可维护性和可扩展性。其本质是“封装遍历变化”,屏蔽不同集合的底层差异,为外部提供标准化的遍历体验。
从多语言实现来看,尽管各语言的语法特性、设计理念差异显著,但核心逻辑高度统一,且均能适配自身的语言特性,完整实现迭代器模式的核心价值:
面向对象语言(C#、C++):通过接口/抽象类严格遵循迭代器模式的四大角色,结合语言内置特性(如C#的IEnumerable、C++的模板)实现通用化、规范化的迭代器,贴合经典设计范式,适配企业级系统和高性能场景;
动态语言(Python):利用原生迭代器协议简化实现,无需显式定义抽象接口,更注重实用性和简洁性,通过__iter__和__next__方法快速实现迭代器功能,适配快速开发场景;
Go语言:以“接口为核心”,通过接口定义迭代器和聚合类的契约,结构体实现具体逻辑,轻量化实现解耦目标,贴合高并发、高性能的后端开发需求,代码简洁高效;
纯C语言:通过结构体+函数指针模拟面向对象特性,手动封装数据和遍历行为,虽代码冗余,但底层可控性强,适配嵌入式、底层开发等资源受限场景,完美还原迭代器模式“解耦遍历与存储”的核心思想。
在工程实践中,使用迭代器模式需把握三个核心原则:一是避免过度设计,对于简单集合(如小型数组),直接使用语言内置的遍历方式即可,无需引入迭代器;二是权衡性能与灵活性,高频遍历、低延迟的场景需谨慎使用,或选择轻量级迭代器实现;三是注重接口设计,确保迭代器接口的通用性和扩展性,便于后续新增遍历逻辑和集合类型。
总体而言,迭代器模式是处理集合遍历场景的核心设计工具,尤其在集合类型多样、遍历逻辑复杂、需要隐藏内部结构的场景中价值显著。理解迭代器模式的核心,不在于照搬代码结构,而在于掌握“遍历逻辑与数据存储解耦”的设计思路,合理运用可让代码结构更清晰、职责更单一、扩展更灵活,提升系统的可维护性和复用性。