** 迭代器模式** 是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。
大部分集合使用简单列表存储元素。 但有些集合还会使用栈、 树、 图和其他复杂的数据结构。
无论集合的构成方式如何, 它都必须提供某种访问元素的方式, 便于其他代码使用其中的元素。 集合应提供一种能够遍历元素的方式, 且保证它不会周而复始地访问同一个元素。
如果你的集合基于列表, 那么这项工作听上去仿佛很简单。 但如何遍历复杂数据结构 (例如树) 中的元素呢? 例如, 今天你需要使用深度优先算法来遍历树结构, 明天可能会需要广度优先算法; 下周则可能会需要其他方式 (比如随机存取树中的元素)。
不断向集合中添加遍历算法会模糊其 “高效存储数据” 的主要职责。 此外, 有些算法可能是根据特定应用订制的, 将其加入泛型集合类中会显得非常奇怪。
另一方面, 使用多种集合的客户端代码可能并不关心存储数据的方式。 不过由于集合提供不同的元素访问方式, 你的代码将不得不与特定集合类进行耦合。
迭代器模式的主要思想是将集合的遍历行为抽取为单独的迭代器对象。
除实现自身算法外, 迭代器还封装了遍历操作的所有细节, 例如当前位置和末尾剩余元素的数量。 因此, 多个迭代器可以在相互独立的情况下同时访问集合。
迭代器通常会提供一个获取集合元素的基本方法。 客户端可不断调用该方法直至它不返回任何内容, 这意味着迭代器已经遍历了所有元素。
所有迭代器必须实现相同的接口。 这样一来, 只要有合适的迭代器, 客户端代码就能兼容任何类型的集合或遍历算法。 如果你需要采用特殊方式来遍历集合, 只需创建一个新的迭代器类即可, 无需对集合或客户端进行修改。
你计划在罗马游览数天, 参观所有主要的旅游景点。 但在到达目的地后, 你可能会浪费很多时间绕圈子, 甚至找不到罗马斗兽场在哪里。
或者你可以购买一款智能手机上的虚拟导游程序。 这款程序非常智能而且价格不贵, 你想在景点待多久都可以。
第三种选择是用部分旅行预算雇佣一位对城市了如指掌的当地向导。 向导能根据你的喜好来安排行程, 为你介绍每个景点并讲述许多激动人心的故事。 这样的旅行可能会更有趣, 但所需费用也会更高。
所有这些选择(自由漫步、 智能手机导航或真人向导)都是这个由众多罗马景点组成的集合的迭代器。
class Iterator;
class ConcreteIterator;
typedef int Object;
class Container
{
public:
virtual ~Container() {};
//声明集合接口并描述一个获取迭代器的方法。 其返回值必须是迭代器接口。 如果你计划拥有多组不同的迭代器, 则可以声明多个类似的方法。
virtual Iterator * createIterator() = 0;
virtual Object getItem(int idx) = 0;
virtual int getSize() = 0;
protected:
Container() {};
};
class ConcreteContainer :public Container
{
public:
enum {SIZE = 3};
ConcreteContainer() {
for (int i = 0;i < SIZE;i++)
_objs[i] = i;
};
~ConcreteContainer()
{
}
Iterator * createIterator()
{
return new ConcreteIterator(this);
}
Object getItem(int idx)
{
if (idx < getSize()) return _objs[idx];
return -1;
}
int getSize()
{
return SIZE;
}
private:
Object _objs[SIZE];
};
class Iterator
{
public:
virtual ~Iterator() {};
virtual void first() = 0;
virtual void next() = 0;
virtual bool isDone() = 0;
virtual Object currentItem() = 0;
protected:
Iterator() {}
};
class ConcreteIterator :public Iterator
{
public:
ConcreteIterator(Container*ag, int idx = 0) :_ag(ag), _idx(idx) { //构成函数参数为容器
}
~ConcreteIterator() {}
void first() { _idx = 0; }
void next() { if (_idx < _ag->getSize()) _idx++; }
bool isDone() { return _idx == _ag->getSize(); }
Object currentItem()
{
return _ag->getItem(_idx);
}
private:
Container * _ag;
int _idx;
};
原文:https://www.cnblogs.com/ultramanX/p/14808132.html