迭代器模式
2020-10-30 本文已影响0人
钟离惜
迭代器模式属于数据结构模式。
在GOF的《设计模式:可复用面向对象软件的基础》一书中对迭代器模式是这样说的:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示。
一个聚合对象,就是所谓的对象容器了;作为一个容器,都应该提供一种方法来让别人可以访问它的元素;但是,有的时候,我是不希望遍历容器的人知道我的容器是如何实现的;那该怎么办?就像我在大学那样实现的链表,只提供了从头到尾的遍历,如果我需要从尾到头的遍历呢?是不是我又要添加对应的方法了呢!!!容器的遍历方式千变万化,我们不知道需求是如何的,如果需求变了,那么我们的代码就会发生很大的改动,所以,我们需要去改变;对于上面的代码,当我对同一个链表对象进行多次遍历时,是不是就出现了m_pCurrent对象混乱的局面呢?是的,这一切的一切,都说明,我们必须去将一个容器的内部结构与它的遍历进行解耦,要是出现上面的情况时,我们就无法面对。就好比STL中的容器,它将容器中对象的实现和遍历很好的解耦了,所以,我们就无法知道它的内部是如何组织对象数据的,同时,我们也可以按照我们自己的想法去遍历容器,而不会出现任何差错。在我们的项目中使用迭代器模式就能很好的将容器对象的内部表示与对它的遍历进行解耦。
实现要点
1.迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
2.迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
3.迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。
适用性:
1.访问一个聚合对象的内容而无需暴露它的内部表示。
2.支持对聚合对象的多种遍历。
3.为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。
示例代码
#include <iostream>
#include <vector>
using namespace std;
template<class Item>
class Iterator
{
public:
virtual void first() = 0;
virtual void next() = 0;
virtual Item* currentItem() = 0;
virtual bool isDone() = 0;
virtual ~Iterator() {}
};
template<class Item>
class ConcreteAggregate;
template<class Item>
class ConcreteIterator : public Iterator <Item>
{
ConcreteAggregate<Item> * aggr;
int cur;
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()
{
if (cur < aggr->getLen())
return &(*aggr)[cur];
else
return NULL;
}
virtual bool isDone()
{
return (cur >= aggr->getLen());
}
};
template<class Item>
class Aggregate
{
public:
virtual Iterator<Item>* createIterator() = 0;
virtual ~Aggregate() {}
};
template<class Item>
class ConcreteAggregate :public Aggregate<Item>
{
vector<Item >data;
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();
}
};
int main()
{
Aggregate<int> * aggr = new ConcreteAggregate<int>();
Iterator<int> *it = aggr->createIterator();
for (it->first(); !it->isDone(); it->next())
{
cout << *(it->currentItem()) << endl;
}
delete it;
delete aggr;
return 0;
}