迭代器模式又叫迭代模式。迭代器模式提供了一种顺序访问聚合对象中各元素的方法,隐藏了对象的内部结构,为遍历不同聚合结构,提供了如“开始”、“下一个”、“是否遍历结束”、“当前遍历位置”等统一的操作接口。即该模式在遍历容器之前,新定义了一个外部类,容器把对内部对象的遍历访问委派外部类。

在使用该模式之前,我们应该明白迭代器模式是用来解决什么问题的,或者说,如果不使用该模式而使用其他方法会存在什么问题。遍历容器的方法有两个:

  • 由容器自己实现遍历,即在容器内直接提供遍历方法。但该方法有个缺点就是容器类承担了过多的功能,一方面要负责容器内元素的增删改查,还需要提供一个遍历方法,很容易引起程序混乱甚至运行出错。

  • 让调用者自己实现遍历。但这个很明显的缺点就是暴露数据细节给客户,这是很危险的操作。

优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。


类图如下:


示例代码如下:

#include <iostream>
using namespace std;
typedef int Object;
#define SIZE 5

/* 抽象迭代器基类 */
class MyIterator
{
public:
	virtual void First() = 0;
	virtual void Next() = 0;

	virtual bool IsDone() = 0;
	virtual Object CurrentItem() = 0;

};

/* 抽象容器基类 */
class Aggregate
{
public:
	virtual MyIterator *CreateIterator() = 0;
	virtual Object getItem(int index) = 0;
	virtual int getSize() = 0;
};

/* 具体迭代器子类 */
class ContreteIterator : public MyIterator
{
public:
	/* 根据传入的容器类,初始化迭代器类 */
	ContreteIterator(Aggregate * ag)
	{
		_ag = ag;
		_current_index = 0;
	}
	virtual void First()
	{
		_current_index = 0; //让当前 游标 回到位置0
	}
	virtual void Next()
	{
		if (_current_index < _ag->getSize())
		{
			_current_index++;
		}
	}

	virtual bool IsDone()
	{
		return (_current_index == _ag->getSize());
	}

	virtual Object CurrentItem()
	{
		return _ag->getItem(_current_index);
	}
private:
	int _current_index;
	Aggregate * _ag;
};

/* 具体容器子类 */
class ConcreteAggregate : public Aggregate
{
public:
	/* 给容器内元素初始化 */
	ConcreteAggregate()
	{
		for (int i = 0; i < SIZE; i++)
		{
			object[i] = i + 100;
		}
	}

	/* 创建该容器对象自己的迭代器对象 */
	virtual MyIterator *CreateIterator()
	{
		return new ContreteIterator(this); //让迭代器 持有一个 集合的 引用
	}

	/* 获取当前索引对应的值 */
	virtual Object getItem(int index)
	{
		return object[index];
	}
	/* 获取当前容器内元素个数 */
	virtual int getSize()
	{
		return SIZE;
	}
private:
	Object object[SIZE];
};

void main()
{
	/* 创建容器 */
	Aggregate * ag = new ConcreteAggregate;

	/* 创建该容器的迭代器 */
	MyIterator *it = ag->CreateIterator();

	/* 从当前容器索引遍历元素 */
	for (; !(it->IsDone()); it->Next())
	{
		cout << it->CurrentItem() << "  ";
	}
	cout << endl;
	delete it;
	delete ag;
	system("pause");
	return;
}

代码运行结果如下: