迭代器模式:

  迭代器模式允许你访问一个数据项序列中的所有元素,而无须关心序列是什么类型(数组、链表、列表或任何其他类型)。它能有效地构建一个数据管道,经过一系列不同的转换或过滤后再从管道的另一端出来。迭代器模式就是提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示。

迭代器模式的角色:

  1. 抽象迭代器(Iterator):接口声明了遍历集合所需的操作(获取下一个元素、获取当前位置和重新开始迭代等)。
  2. 具体迭代器(ConcreteIterator):实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度。这使得多个迭代器可以相互独立地遍历同一个集合。
  3. 抽象聚合(Aggregate):接口声明一个或多个方法来获取与集合兼容的迭代器。返回方法的类型必须被声明为迭代器接口。
  4. 具体聚合(ConcreteAggregate):会在客户端请求迭代器时返回一个特定的具体迭代器类实体。
  5. 客户端(Client):通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。

迭代器模式适用性:

  1. 当集合背后为复杂的数据结构,且你希望对客户端隐藏其复杂性时(出于使用便利性或安全性的考虑),可以使用迭代器。
  2. 可以减少程序中重复的遍历代码。
  3. 如果你希望代码能够遍历不同的甚至是无法预知的数据结构,可以使用迭代器。

优点:

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

缺点:

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

eg:

class Iterator
{
public:
	Iterator(){}
	virtual ~Iterator(){};
	virtual string First() = 0;
	virtual string Next() = 0;
	virtual string GetCur() = 0;
	virtual bool IsEnd() = 0;
};
 
class Aggregate
{
public:
	virtual int Count() = 0;
	virtual void Push(const string &strValue) = 0;
	virtual string POp(const int cnt) = 0;
	virtual Iterator* CreateIterator() = 0;
};
//-----------------------------------------------------
class ConcreteIterator : public Iterator
{
public:
	ConcreteIterator(Aggregate *p_aggregate):m_aggregate(p_aggregate),m_cnt(0){}
	
	string First()
	{
		return m_aggregate->POp(0);
	}
 
	string Next()
	{
		string str;
		m_cnt++;
		if (m_cnt < m_aggregate->Count())
		{
			str = m_aggregate->POp(m_cnt);
		}
 
		return str;
	}
 
	string GetCur()
	{
		return m_aggregate->POp(m_cnt);
	}
 
	bool IsEnd()
	{
		return m_cnt >= m_aggregate->Count() ? true : false;
	}
 
	~ConcreteIterator(){ }
 
private:
	Aggregate *m_aggregate;
	int m_cnt;
};
class ConcreteAggregate : public Aggregate
{
public:
	ConcreteAggregate() :m_pIterator(NULL)
	{
		m_vecItem.clear();
	}
 
	~ConcreteAggregate()
	{
		if (NULL != m_pIterator)
		{
			delete m_pIterator;
			m_pIterator = NULL;
		}
	}
 
	int Count()
	{
		return m_vecItem.size();
	}
 
	void Push(const string &strValue)
	{
		m_vecItem.push_back(strValue);
	}
 
	string POp(const int cnt)
	{
		string str;
		if (cnt < Count())
		{
			str = m_vecItem[cnt];
		}
		return str;
	}
 
	Iterator* CreateIterator()
	{
		if (NULL == m_pIterator)
		{
			m_pIterator = new ConcreteIterator(this);
		}
 
		return m_pIterator;
	}
 
private:
	vector<string> m_vecItem;
	Iterator *m_pIterator;
};
//-----------------------------------------------------
//use
	ConcreteAggregate* pName = new ConcreteAggregate();
    pName->Push("hello");
    pName->Push("word");
    pName->Push("cxue");

	Iterator* iter =pName->CreateIterator();
    string strItem = iter->First();
    while (!iter->IsEnd())
    {
        cout << iter->GetCur() << " is ok" << endl;
        iter->Next();
    }