迭代器模式:
迭代器模式允许你访问一个数据项序列中的所有元素,而无须关心序列是什么类型(数组、链表、列表或任何其他类型)。它能有效地构建一个数据管道,经过一系列不同的转换或过滤后再从管道的另一端出来。迭代器模式就是提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示。
迭代器模式的角色:
- 抽象迭代器(Iterator):接口声明了遍历集合所需的操作(获取下一个元素、获取当前位置和重新开始迭代等)。
- 具体迭代器(ConcreteIterator):实现遍历集合的一种特定算法。迭代器对象必须跟踪自身遍历的进度。这使得多个迭代器可以相互独立地遍历同一个集合。
- 抽象聚合(Aggregate):接口声明一个或多个方法来获取与集合兼容的迭代器。返回方法的类型必须被声明为迭代器接口。
- 具体聚合(ConcreteAggregate):会在客户端请求迭代器时返回一个特定的具体迭代器类实体。
- 客户端(Client):通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。
迭代器模式适用性:
- 当集合背后为复杂的数据结构,且你希望对客户端隐藏其复杂性时(出于使用便利性或安全性的考虑),可以使用迭代器。
- 可以减少程序中重复的遍历代码。
- 如果你希望代码能够遍历不同的甚至是无法预知的数据结构,可以使用迭代器。
优点:
- 它支持以不同的方式遍历一个聚合对象。
- 迭代器简化了聚合类。
- 在同一个聚合上可以有多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。符合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();
}