迭代器模式
迭代器模式提供了一种方法以顺序访问一个聚合对象(Collections)中的各个元素,而不需要暴露该对象的内部表示。迭代器模式将迭代逻辑封装在一个独立的迭代器对象中,使得客户端可以独立于聚合对象遍历聚合对象中的元素。
结构
迭代器模式示意图
迭代器模式将容器和迭代方式分离,使得容器可以专注于存储数据,而迭代器可以专注于遍历数据。
迭代器模式的核心是迭代器接口,该接口定义了遍历容器的方法(获取下一个元素、判断是否还有元素等)。具体的迭代器类实现了迭代器接口,负责实现遍历容器的逻辑。
迭代器的生命周期管理由容器类负责,容器类负责创建迭代器对象,并在迭代结束后销毁迭代器对象。在特殊情况下,容器类也应当允许客户端传入自定义的迭代器对象。
应用场景
- 希望对客户端隐藏容器内部的数据结构,同 时提供一种统一的遍历接口时
- 希望同种遍历逻辑可以适用于多种类似的容器时
优缺点
优点
- 单一职责原则:将容器的遍历逻辑与容器本身分离,使得容器可以专注于存储数据。
- 开闭原则:可以在不修改已有容器代码的情况下通过创建新的迭代器类来实现新的遍历逻辑。
- 可以存在多个迭代器对象,允许并行遍历容器。
缺点
- 由于迭代器模式引入了迭代器对象,可能会增加程序的复杂度和内存开销,影响迭代效率。
代码示例
下面以二叉树的中序遍历为例,展示了一个简单的迭代器模式的实现。
Tree
是一个聚合类(或集合),它包含一个树形结构。InOrderIterator
是一个具体的迭代器,它实现了遍历 Tree
的特定算法(中序遍历)。
关键在于,Tree
类实现了 __iter__
方法,这使得它成为了一个可迭代对象。当客户端代码(例如 for
循环)需要遍历 Tree
时,它会调用 __iter__
方法来获取一个 InOrderIterator
的实例。这个迭代器对象维护着遍历的状态(例如,使用一个栈来辅助遍历),并实现了 __next__
方法来逐个返回树中的节点。
这种方式将遍历的复杂逻辑从 Tree
类中分离出来,使得客户端可以像遍历一个简单的列表一样遍历一个复杂的树结构,而无需关心其内部实现。
值得注意的是,Python 内置对 迭代器 有良好的支持,凡是实现了魔术方法 __iter__
和 __next__
的对象都视作实现了迭代器协议,可以当做迭代器使用。
如果我们在下面的代码中为 Tree
类实现 __iter__
(内部返回 TreeIterator
对象),那么我们就可以直接使用 for node in tree
来遍历树中的所有节点,使得代码更加符合语义和可读。
如果需要限制树中的节点都为同一类型的值,可以使用 TypeVar
和 Generic
来实现泛型。