迭代器模式将树或图的遍历逻辑封装在独立迭代器类中,节点类仅负责数据存储与基础访问,聚合类提供createIterator()方法;迭代器用栈、队列或生成器实现惰性遍历,统一返回标准化输出单元,并通过Set防图结构重复访问。

直接用迭代器模式封装树或图的遍历逻辑,客户端只管调用 next() 和 hasNext(),完全不用知道它是递归、栈模拟,还是用了生成器、BFS队列——这才是“隐藏内部存储逻辑”的实质。
把遍历行为从数据结构里抽出来
树节点类(比如目录、菜单项、AST节点)只负责存数据和子节点,不写任何遍历方法。遍历交给独立的迭代器类实现。这样修改遍历方式(比如从前序改成中序)不影响节点定义,也不会污染业务逻辑。
- 节点类保持干净:只有
getName()、getChildren()这类基础访问器 - 迭代器类持有对根节点的引用,自行管理遍历状态(如栈、队列、递归深度)
- 聚合类(如
TreeContainer)只提供createIterator()方法,不暴露内部字段
用生成器函数实现惰性、可中断的树遍历
JavaScript 中用 function* 写迭代器最自然;Java 可用 Iterator<T> 接口配合内部状态机。关键是要支持“按需计算”,尤其对大结构:
- 每次
next()只展开当前层级一个节点,不预先构建整棵树的扁平数组 - 可在
for...of中随时break或return,避免无谓遍历 - 示例:二叉树中序迭代器内部用栈模拟递归,
next()每次吐出下一个中序节点,不缓存全部结果
统一输出变量的关键是标准化元素形态
无论原始结构多嵌套(如配置对象含三层嵌套对象+数组),迭代器返回的每个元素都应是结构一致的“输出单元”:
- 可以是键值对:
{ path: 'db.host', value: 'localhost' } - 也可以是带元信息的对象:
{ node: thisNode, depth: 2, isLeaf: true } - 避免返回原始节点引用,防止客户端误改内部状态;用只读包装或深拷贝必要字段
图结构要额外处理环与重复访问
树天然无环,图则必须防重入。在迭代器内部维护已访问标识(如 Set<NodeId>):
- 每次取出节点前先检查是否已遍历,跳过重复项
- 若需支持多种图遍历策略(DFS/BFS/拓扑),让迭代器接收策略参数,而不是硬编码
- 对外仍保持同一套
hasNext()/next()接口,切换策略不改客户端代码

















