行为型模式--Iterator模式(迭代器)对象行为型模式
一. 意图
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.
二. 适用性
访问一个聚合对象的内容而无需暴露它的内部表示.
支持对聚合对象的多种遍历(例如顺序遍历list, 倒序遍历list等)
为遍历不同的聚合结构提供一个统一的接口(支持多态迭代).(例如顺序遍历中, 可以遍历list, vector等)
这一模式的关键思想是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中. 迭代器类定义了一个访问该列表元素的接口. 迭代器对象负责跟踪当前的元素.
三. 模式结构
图1
四. 角色说明
Iterator(迭代器)
—迭代器定义访问和遍历元素的接口.
ConcreteIterator(具体迭代器)
—具体迭代器实现迭代器接口.
—对该聚合遍历时跟踪当前位置.
-ConcreteIterator跟踪聚合中的当前对象,并能够计算出待遍历的后继对象.
Aggregate(聚合)
—聚合定义创建相应迭代器对象的接口.
ConcreteAggregate(具体聚合)(例如list, vector, map)
—具体聚合实现创建相应迭代器的接口, 该操作返回ConcreteIterator的一个适当的实例.
五. 说明
1. 它支持以不同的方式遍历一个聚合
2. 迭代器简化了聚合的接口. (聚合中就不需要包含遍历相关的接口)
3. 在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态. 因此你可以同时进行多个遍历.
4. 迭代器分内部迭代器和外部迭代器. C++的STL中属于外部迭代器, 它需要客户主动推进遍历的步伐, 你可以在获得某个聚合对象后做一些事情. 内部迭代器则有迭代器本身来推动遍历的步伐, 因为是内部, 当你需要对聚合对象做一些什么事情时, 必须在迭代前对迭代器设置好(例如设置一个回调函数指针).
5. 附加的迭代器操作迭代器的最小接口由First, Next, IsDone和CurrentItem操作组成.
6. 在C++中使用多态的迭代器 它们要求用一个FactoryMethod动态的分配迭代器对象. 因此仅当必须多态时才使用它们. 否则使用在栈中分配内存的具体的迭代器. 多态迭代器有另一个缺点: 客户必须负责删除它们. 例如STL中的 list::erace(); Proxy模式提供了一个补救方法. 我们可使用一个栈分配的Proxy作为实际迭代器的中间代理. 该代理在其析构器中删除该迭代器. 这样当该代理生命周期结束时, 实际迭代器将同它一起被释放. 即使是在发生异常时, 该代理机制能保证正确地清除迭代器对象. 这就是著名的C++“资源分配即初始化”的一个应用.
7. 迭代器可有特权访问 从该模式的结构知道迭代器和聚合紧密耦合.
8. 空迭代器 一个空迭代器(NullIterator)是一个退化的迭代器, 它有助于处理边界条件.
六. 我的理解:
1. 迭代模式中, 用得最多的那就是C++的STL了, list, vector, set, map等.
通常我是这么用
struct STStudent
{
STStudent();
~STStudent();
STStudent(const STStudent& stStudent); // 拷贝构造函数
STStudent& operator=(const STStudent& stStudent); // 拷贝操作符
void Release();
std::string m_strName;
};
typedef std::vector<STStudent*> STStudentVector; // STStudent对象数组, 模板参数是指针
typedef STStudentVector::iterator STStudentVectorIterator; // 迭代器
typedef STStudentVector::const_iterator STStudentVectorConstIterator; // 常量迭代器.
特别是聚合是一个很大的数据结构/类时, 模板参数使用指针可以避免过大的拷贝.
typedef std::vector<STStudent> STStudentVector; // 迭代过程中, 拷贝非常频繁, 那么sizeof(STStudent)很大时, 效率会很低.
模板参数是指针的缺点是, 需要自己手动删除聚合.
可以看到, std::vector怎么存储STStudent*我们并不需要知道, 我们只使用STStudentVectorIterator就可以完成vector的元素访问. 这就是Iterator模式的实现目的.
使用
STStudentVector stStudentVector;
...
STStudentVectorIterator iter;
// 这里就是使用外部遍历
for(iter = stStudentVector.begin(); iter = stStudentVector.end(); ++iter);
// 也可以这样
for(int i = 0; i < stStudentVector.size(); ++i);
七. 相关模式
Composite: 迭代器常被应用到象复合这样的递归结构上.
Factory Method: 多态迭代器靠Factory Method来例化适当的迭代器子类.
Memento: 常与迭代器模式一起使用. 迭代器可使用一个memento来捕获一个迭代的状态。迭代器在其内部存储memento