Iterator模式
type
status
date
slug
summary
tags
category
icon
password
comment_flag
SLUGS
目的
提供一种对集合中的元素进行有序遍历的方式,而不关心不暴露集合的底层结构。
好处
- 正如目的中所谈到,提供一种不关心不暴露底层数据结构的遍历方式
- 将遍历机制和集合的结构分离,可以允许我们定义不同迭代策略的迭代器,而不是在内部的数据结构中进行遍历。
适用范围
- 在不暴露内部结构的情况下,对聚合对象进行迭代访问
- 对聚合对象的多次遍历有需求
- 提供用于遍历不同聚合结构的统一接口(即支持多态迭代)
模式结构
评价
- 对内部结构不同的聚合对象的遍历进行很好的支持
- iterator简化了聚合对象遍历接口
- 对聚合对象的多次遍历进行很好的支持
联系
- Composite模式:iterator模式常被用于composite模式的符合结构
- Factory模式:多态迭代器依赖于工厂方法来实例化适当的Iterator子类。
实现
关注的问题
谁来控制集合的迭代?内部迭代器和外部迭代器
怎么定义迭代算法?
- Aggregate本身定义算法——Cursor mode光标模式
- iterator定义算法——iterator如何访问数据
迭代器有哪些常见操作?
First
Next
hasNext
IsDone
CurrentItem
其他:实现多态迭代器,空迭代器
示例
场景
现在有两家餐厅:煎饼店和午餐饭店,它们想要合并。两家店的菜单需要统一起来,以便服务员给客户看。
但问题是:两家饭店菜单实现方式不一样,也即数据结构不一样,一家是通过数组实现的,另一家是动态数组实现的。
如果服务员为顾客提供新菜单是,得分别针对不同数据结构,在底层实现不同的迭代。
代码一
MenuItem.java
PancakeMenu.java
DinnerMenu.java
Waitress.java
Main.java
分析一
代码一的问题在于:
Waitress
类暴露了菜单的底层结构
- 扩展性差,如果新加盟了一家咖啡馆,菜单实现为
HashMap
,那么又得新增迭代代码
- 迭代部分大同小异,代码冗余。
改进
采用iterator设计模式,下图为该模式的结构:
迭代动作被封装成了一个接口
Iterator
,每一种聚合(也就是不同底层实现的集合),都对应了一种具体的迭代器ConcreteIterator
。代码二
创建基本的菜单项类
MenuItem
,包含了各种菜单的共有属性和方法自定义迭代器接口
MyIterator.java
,有hasNext
和next
两种方法实现具体的迭代器接口
PancakeMenuIterator.java
以及DinnerMenuIterator.java
,其中实现的方法依赖于聚合对象的数据结构实现具体聚合(某一对象集合)类并在其中实现创建迭代器的方法,即分别创建
DinnerMenu
和PancakeMenu
类创建服务员类
Waitress
,现在的服务员,不需要清楚菜单的具体设计,打印总菜单时,只需要调用各自菜单的迭代器即可。而且即使扩展增加新的菜单时,也更加容易在
main
函数中运行结果:
分析二
通过上面的代码,可看到,迭代器模式能够不暴露聚合内部的具体实现,而且也让聚合任务减轻,把“游走”的任务放在了迭代器上,简化了聚合的接口和实现,也让任务各得其所。
加粗部分就是
单一责任原则
(一个类应该只有一个引起变化的原因)的体现。之所以我们要让一个类只有一个改变的原因,在于:我们需要避免类的改变,而类的责任越多时,它改变的机率就越大。而且,当类真的改变时,两个责任的代码都可能受到影响。
参考文章:
Loading...