迭代器模式
迭代器模式
一、什么是迭代器模式?
迭代器模式(Iterator Design Pattern):提供一种方式来访问聚合里面的所有元素,而不暴露聚合对象的内部数据结构。
迭代器模式,也称为游标模式,主要用于遍历数据集合。
迭代器模式的几个特点:
- 目的是为了遍历集合数据
- 特点是可以避免集合的内部数据结构暴露,增加集合内部实现的灵活性
迭代器是为了遍历集合数据,所以一个完整的迭代器,肯定是包括集合和迭代器2部分。
迭代器模式,关注重点在于遍历数据,而不是按照什么顺序遍历。
比如说,集合里是按照字母顺序保存的,但使用迭代器遍历时,遍历顺序并不一定是按字母排序。
所以,迭代器并不一定按照结构遍历,而是主要为了遍历数据。
二、为什么要用迭代器模式?
2.1 想要遍历集合的所有数据
迭代器的目的就是为了遍历数据,所以是为了遍历集合,可使用迭代模式。
2.2 不想暴露集合内部数据结构
有些时候,会出现
- 不想被人知道集合内部的数据结构
- 或者可能会修改内部数据结构实现
的情况,这时就需要隐藏内部的数据结构实现。
但是又需要遍历数据,这个时候就可以提供一个迭代器接口给外面调用。
2.3 想要统一集合的遍历结构
假如有很多种集合类型,比如 List、Set、Map、Tree、Graph 等。
每种数据结构是不同的,在实际遍历时需要写的代码也不一样。
比如,遍历树的方式就有前序遍历、中序遍历、后序遍历等,代码都不同。
想要按照统一的方式遍历这些集合,就可以用迭代器来实现。
2.4 想要特殊的遍历方式
有时候,想要按照某种顺序去遍历集合中的数据,可以自定义迭代器是完成。
比如按照字母顺序遍历,按照添加顺序遍历,按照添加顺序逆序遍历等等。
这个时候,可以为不同的遍历方式提供不同的迭代器实现。
三、怎么用迭代器模式?
迭代器模式中的角色包括:
- 迭代器(Iterator):定义了遍历集合数据的接口
- 具体迭代器(ConcreteIterator):实现了迭代器接口的具体迭代器,和具体的集合数据结构绑定
- 集合(Aggregate):集合接口,定了了创建迭代器的接口
- 具体集合(ConcreteAggregate):实现了集合接口的具体集合,提供属于自己的迭代器实现
迭代器模型结构:
示例程序结构:
迭代器(Iterator):
1 | public interface Iterator<T> { |
集合(Aggregate):
1 | public interface Aggregate<T> { |
具体集合(ConcreteAggregate):
1 | public class BookShelf implements Aggregate<Book> { |
具体迭代器(ConcreteIterator):
1 | public class BookShelfIterator implements Iterator<Book> { |
四、迭代器模式有什么优缺点?
优点:
- 统一集合的遍历方式,特别是对于复杂结构来说更友好
- 集合与迭代分离,耦合性低,很方便扩展迭代器
- 隐藏集合的数据结构,提高集合内部实现的灵活性
缺点:
- 客户端只能调用已有的迭代器,集合实现者需提供足够的迭代器实现
- 迭代器增加了类的数量,在一定程度上增加了程序的复杂性
五、实际场景
- JDK 中的集合类,基本都实现了 Iterator 迭代器
- ArrayList 中提供了正序和逆序2种迭代器
- LinkedHashMap 提供了按照添加顺序遍历的迭代器接口