现在有一个集合。其内部元素的存储方式可能比较复杂。为了让用户在不用关心其内部表示的情况下对其元素进行访问,于是创建了一个迭代器用于对集合的各个元素进行访问。为了给用户提供一个更友好且强大的接口类,于是对迭代器以组合的形式进行封装,得到一个管理类。用户直接操作该管理类即可得到指定元素,或通过管理类直接得到迭代器,通过迭代器访问具体元素。这就是迭代器模式。
STL中使用了迭代器。以vector为例。为了便于访问元素,定义了迭代器Iterator。将Iterator以组合的形式封装成一个管理类,即vector。用户使用时,使用的是管理类vector。用户可以通过管理类vector直接访问集合元素,或者通过vector来获取迭代器Iterator,通过Iterator来访问集合元素。
1. 定义迭代器Iterator基类及管理类基类Aggregate
两个基类分别规定了迭代器类与管理类的标准接口。
//迭代器基类Iterator
template<class Item>
class Iterator
{
public:
virtual void first() = 0;
virtual void next() = 0;
virtual Item* currentItem() = 0;
virtual bool isDone() = 0;
};
//管理类基类Aggregate
template<class Item>
class Aggregate
{
public:
virtual Iterator<Item>* createIterator() = 0;
};
2. 定义迭代器类派生类及管理类派生类
实现两个基类所定义的标准接口。
//迭代器派生类ConcreteIterator
template<class Item>
class ConcreteIterator : public Iterator <Item>
{
public:
ConcreteIterator(ConcreteAggregate<Item>*a) :_aggr(a), _cur(0) {}
virtual void first() { _cur = 0; }
virtual void next() { if (_cur < _aggr->getLen()) _cur++; }
virtual Item* currentItem() { return (cur < _aggr->getLen()) ? &(*_aggr)[cur] : NULL; }
virtual bool isDone() { return (_cur >= _aggr->getLen()); }
protected:
ConcreteAggregate<Item> * _aggr;
int _cur;
};
//管理类派生类ConcreteAggregate
template<class Item>
class ConcreteAggregate :public Aggregate<Item>
{
public:
ConcreteAggregate()
{
_data.push_back(1);
_data.push_back(2);
_data.push_back(3);
}
virtual Iterator<Item>* createIterator()
{
return new ConcreteIterator<Item>(this);
}
Item& operator[](int index)
{
return _data[index];
}
int getLen()
{
return _data.size();
}
protected:
vector<Item > _data;
};
3. 用户使用
用户使用时,将管理类的派生类指针赋给管理类基类指针。由于接口都是标准的,故用户直接使用该基类即可。
同理,用户可使用管理类的接口创建一个迭代器指针,然后将该指针赋值给迭代器基类指针,然后用户直接使用迭代器基类即可。
void main()
{
Aggregate<int> * aggr = new ConcreteAggregate<int>();
Iterator<int> *it = aggr->createIterator();
for (it->first(); !it->isDone(); it->next())
{
cout << *(it->currentItem()) << endl;
}
}