迭代器模式解决什么
迭代器模式提供按顺序访问聚合元素的统一方式,同时不暴露内部结构。今天的语言大多已经内置这一能力:遍历语法、生成器、流式接口都是它的现成形态,因此自定义实现主要用于树形结构、跨数据源组合与惰性计算这类内建遍历覆盖不到的场景。使用时要明确两个约定:遍历过程中容器被修改时如何表现,以及迭代器失效后的行为。
基本信息
| 意图 | 统一遍历协议,封装内部数据结构 |
|---|---|
| 常见形态 | 下一个元素判断取值的方法对,或语言生成器 |
| 适用 | 树形结构、多数据源合并、惰性序列 |
| 风险 | 遍历过程中容器被修改导致行为未定义 |
典型使用场景
- 树形结构深度优先遍历:用生成器递归产出节点,调用方不必关心递归细节
- 多数据源合并读取:把分页接口包装成统一迭代,调用方按顺序取用
- 惰性序列处理:元素按需计算,避免一次性构造大集合
- 自定义容器类型:为内部结构提供标准遍历能力,便于配合通用算法
- 测试替身:为假数据源提供与真实数据源一致的遍历接口
生成器形态
生成器形态
# 树形结构深度优先遍历:调用方只面对统一的顺序
def walk(node):
yield node.value
for child in node.children:
yield from walk(child)
# 使用:不需要暴露 children 结构
for value in walk(root):
print(value)实现要点
| 要点 | 正确做法 | 常见问题 |
|---|---|---|
| 失效语义 | 明确列出修改容器时的行为 | 遍历中修改导致结果错乱或抛出不一致的异常 |
| 游标位置 | 游标封装在迭代器内部 | 暴露游标字段,调用方可任意跳转,封装目标落空 |
| 一次性 | 明确迭代器能否重复遍历 | 多次遍历得到空结果,调用方困惑 |
| 惰性求值 | 异常在取元素时抛出,需说明时机 | 调用方以为构造成功,取用时才失败 |
| 资源释放 | 遍历结束或中断时释放资源 | 提前退出导致连接或文件句柄未释放 |
语言已内置遍历协议时,优先实现该协议而不是自造方法对:这样对象可以直接用于标准循环、流式操作与通用工具函数,不必为每种用法额外适配。
遍历过程中修改容器是最常见的缺陷来源:不同实现对同类操作的表现可能不一致,有的立即失败,有的静默跳过元素。若业务确实需要边遍历边修改,应先收集待处理元素再统一修改。
落地检查清单
- 遍历过程中修改容器的行为有明确定义并写进文档
- 迭代器可重复使用与否有说明
- 提前中断遍历时资源能正确释放
- 自定义迭代器有对应测试,覆盖空集合与单元素情形