1.1 基本概念
迭代器模式(Iterator Pattern):提供了一种方法来访问聚合对象,而不用暴露这个对象的内部。
聚合对象的两个基本功能:
(1)存储内部数据;
(2)遍历内部数据;
1.2 模式结构
(1)Iterator(抽象迭代器)
抽象迭代器定义了访问和变量 元素的接口,用于获取第一个元素的first(),访问下一个元素的next(),用于获取当前元素的current()。
(2)ConcreteIterator(具体迭代器)
具体迭代器实现了抽象迭代器接口,完成对聚合对象的遍历,同时在对聚合进行遍历时跟踪其当前位置
(3)Aggregate(抽象聚合类或称抽象容器)
抽象聚合类用于存储对象,并定义创建相应迭代器对象的接口,声明一个 createIterator() 方法,用于创建一个迭代器对象。
(4)ConcreteAggregate(具体聚合类或称具体容器)
具体聚合类实现了创建相应迭代器的接口,实现了在聚合类中声明的 createIterator() 方法,该方法返回一个对应的具体迭代器实例。
- 容器部分,内部可以存放一系列数据,并提供迭代器调用接口。
- 迭代器部分,内部含有对容器部分的调用,并获得容器内部提供的方法。
具体容器和具体迭代器两者是相互调用的,也就是说容器调用了迭代器,然后通过迭代器调用了容器内部自身的方法来实现封装。
1.3 优缺点
优点:
(1)支持以不同的方式遍历一个聚合对象。迭代器可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。同时其封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心;
(2)在迭代器模式中,增加新的聚合类和迭代器都很方便,不需要修改原有代码,满足开闭原则;
缺点:
由于存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,一定程度上增加了系统的复杂性。
1.4 应用场景
(1)访问一个聚合对象的内容而无须暴露它的内部表示。将聚合对象的访问与内部数据的存储分离,使得访问聚合对象时,无须了解其内部实现细节;
(2)需要为聚合对象提供多种遍历方式;
(3)为遍历不同的聚合结构提供一个统一的接口。
1.5 举例
电视机遥控器可以看做一个迭代器实例,电视机遥控器可以实现对电视机频道集合的遍历操作。
#include<iostream>
#include <vector>
#include <string>
// 具体处理者 Department manager
using namespace std;
#define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
/**
* @brief TVIterator 电视机遥控器类
* @brief (抽象迭代器类) 声明迭代器所具有的方法
*/
class TVIterator
{
public:
TVIterator(){};
virtual ~TVIterator(){};
virtual string First() = 0;
virtual string Next() = 0;
virtual string GetCur() = 0;
virtual bool IsEnd() = 0;
};
/**
* @brief TelevisionAggregate 电视机类
* @brief 抽象聚合类 声明用于创建 具体迭代器对象的CreateIterator() 方法
*/
class TelevisionAggregate
{
public:
TelevisionAggregate(){};
virtual ~TelevisionAggregate(){};
virtual int Count() = 0;
virtual void Push(const string &strValue) = 0;
virtual string Pop(const int index) = 0;
virtual TVIterator *CreateIterator() = 0;
};
/**
* @brief TclTVIterator 具体聚合类
* @brief 具体迭代器类
*/
class TclTVIterator : public TVIterator
{
public:
TclTVIterator(TelevisionAggregate *pAggregate) : TVIterator()
{
m_nCurrent = 0;
m_Aggregate = pAggregate;
}
string First()
{
return m_Aggregate->Pop(0);
}
string Next()
{
string strRet;
m_nCurrent++;
if(m_nCurrent < m_Aggregate->Count())
{
strRet = m_Aggregate->Pop(m_nCurrent);
}
return strRet;
}
string GetCur()
{
return m_Aggregate->Pop(m_nCurrent);
}
bool IsEnd()
{
return ((m_nCurrent >= m_Aggregate->Count()) ? true : false);
}
private:
int m_nCurrent;
TelevisionAggregate *m_Aggregate;
};
/**
* @brief TclTelevisionAggregate TCL电视机类
* @brief 具体聚合类
*/
class TclTelevisionAggregate : public TelevisionAggregate
{
public:
TclTelevisionAggregate() : m_pIterator(NULL)
{
m_vecItems.clear();
}
~TclTelevisionAggregate()
{
if(m_pIterator != NULL)
{
delete m_pIterator;
m_pIterator = NULL;
}
}
TVIterator *CreateIterator()
{
if(m_pIterator == NULL)
{
m_pIterator = new TclTVIterator(this);
}
return m_pIterator;
}
int Count()
{
return m_vecItems.size();
}
void Push(const string &strValue)
{
m_vecItems.push_back(strValue);
}
string Pop(const int index)
{
string strRet;
if(index < Count())
{
strRet = m_vecItems[index];
}
return strRet;
}
private:
TVIterator *m_pIterator;
vector<string> m_vecItems;
};
int main(int argc, char **argv)
{
TclTelevisionAggregate *pTclTelevision = new TclTelevisionAggregate();
if(pTclTelevision == NULL)
return -1;
pTclTelevision->Push("CCTV-1");
pTclTelevision->Push("CCTV-2");
pTclTelevision->Push("CCTV-3");
TVIterator *iter = NULL;
iter = pTclTelevision->CreateIterator();
if(iter != NULL)
{
string strItem = iter->First();
while(!iter->IsEnd())
{
cout << iter->GetCur() << " is ok" << endl;
iter->Next();
}
}
SAFE_DELETE(pTclTelevision);
//SAFE_DELETE(iter);
return 0;
}
参考文献:
【1】C++之迭代器(Iterator)模式 - 古月居