作用
提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示。簡單的來講,就是提供了一個索引,這個索引只能順序的訪問,並且不知道該對象的內部表示。比如我們經常用到的for循環語句,一般用作遍歷數組,其中的 ++i;其作用是每次循環之後i的值加1,這樣就能訪問下一個(下下一個)數組中的元素,也就是從頭至尾的遍歷了數組。將i抽象化後並使其能夠通用,則就形成了iterator模式。
迭代器模式是每個程序員無意之間接觸最早的設計模式,在STL編程中,每一種容器都有與之相關的自己的迭代器。
舉個例子
假設雞腿的包裝是線性的,每次買雞腿,售貨員都從最上面拿出來一個,以此類推,而你不知道這些雞腿包裝的具體結構,但是你通過售貨員又能夠知道這包雞腿裏面的所有雞腿的味道(當然需要花錢一個個買,要不然誰給你看)。售貨員可以看作是你訪問這些雞腿的一個迭代器。
優點
- 它支持以不同的方式遍歷一個聚合對象。
- 迭代器簡化了聚合類。
- 在同一個聚合上可以有多個遍歷。
- 在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。
- 職責分明,遍歷和存儲數據的職責分離。
缺點
由於迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
使用場景
- 訪問一個聚合對象的內容而無須暴露它的內部表示。
- 需要爲聚合對象提供多種遍歷方式。
- 爲遍歷不同的聚合結構提供一個統一的接口。
注意事項
迭代器模式就是分離了集合對象的遍歷行爲,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明地訪問集合內部的數據。
UML 結構圖
例子
#include<iostream>
using namespace std;
template <typename T>
class ConcreateAggregate //以簡單的List爲例說明下迭代器
{
public:
ConcreateAggregate()
{
}
virtual ~ConcreateAggregate()
{
delete[] m_pData;
m_pData = NULL;
}
void setList(int nSize)
{
m_nSize = nSize;
m_pData = new T[nSize];
}
void append(const T& t)
{
static int nIndex = 0;
m_pData[nIndex++] = t;
}
inline int size() const { return m_nSize; }
inline const T& at(int nIndex)
{
return (nIndex < m_nSize ? m_pData[nIndex] : T());
}
class Itreator : public ConcreateAggregate<T>
{
public:
Itreator(ConcreateAggregate* p) : m_pAggreate(p)
{
}
virtual ~Itreator()
{
m_pAggreate = NULL;
m_nIndex = 0;
}
T value(int nIndex) const
{
return m_pAggreate->at(nIndex);
}
inline bool isDone()
{
return m_nIndex == m_pAggreate->size();
}
inline void next()
{
m_nIndex < m_pAggreate->size() ? ++m_nIndex : m_nIndex;
}
T current() const
{
return m_pAggreate->at(m_nIndex);
}
private:
int m_nIndex{0};
ConcreateAggregate* m_pAggreate{NULL};
};
private:
int m_nSize{0};
T* m_pData;
};
int main(int argc, char* argv[])
{
#if 0
ConcreateAggregate<int> pData; //同樣的也可以以對象的形式創建
pData.setList(4);
#endif
ConcreateAggregate<int>* pData = new ConcreateAggregate<int>();
pData->setList(4);
for(int nIndex = 0; nIndex < 4; ++nIndex)
{
pData->append(nIndex);
}
ConcreateAggregate<int>::Itreator* itor = new ConcreateAggregate<int>::Itreator(pData);
cout << itor->value(1) << " " << pData->at(2) << endl;
for(; false == itor->isDone(); itor->next())
{
cout << itor->current() << " ..." << endl;
}
delete pData;
pData = NULL;
delete itor;
itor = NULL;
return 0;
}