意图:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
上下文:集合对象内部结构常常变化各异。对于这些集合对象,能否在不暴露其内部结构的同时,让外部Client透明地访问其中包含的元素,同时让这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供可能?
迭代器模式静态类图
Iterator:定义访问和遍历元素的接口(.NET中定义了标准的IEnumrator接口)。ConcreteIterator:实现Iterator接口,同时在对Aggregate遍历时跟踪当前的位置。Aggregate:定义创建相应Iterator对象的接口(.NET中定义了标准的IEnumrable接口)。ConcreteAggregate:实现创建相应Iterator对象的接口,该操作返回一个适当的ConcreteIterator实例。
注意:.NET中的foreach关键字在编译时会自动创建迭代器对象,并使用该对象对集合进行遍历。.NET中的yield return关键字使得定义迭代器对象更加容易。
迭代器模式(Iterator)结构图
测试代码:
额外需要的知识:运算符[ ]的重载,vector的用法。
#include <iostream>
#include <list>
#include <array>
#include <vector>
using namespace std;
//Iterator迭代器抽象类
class Iterator
{
public:
virtual void* First() = 0;
virtual void* Next() = 0;
virtual bool IsDone() = 0;
virtual void* CurrentItem() = 0;
};
//Aggregate聚集抽象类
class Aggregate
{
public:
virtual Iterator *CreateIterator() = 0;
};
//ConcreteAggregate具体聚集类 继承Aggregate
class ConcreteAggregate:public Aggregate
{
public:
vector<void*> items;
// Aggregate interface
public:
Iterator *CreateIterator();
int getCount() const;
//既可以作为左值,也可以作为又值
void** operator[](unsigned int index){
if(items.size() <= index){
items.resize(index+1);
}
return &items[index];
}
};
class ConcreteIterator:public Iterator
{
public:
ConcreteAggregate *ca;
int current;
ConcreteIterator(ConcreteAggregate *c):ca(c){
this->current = 0;
}
virtual void* First();
virtual void* Next();
virtual bool IsDone();
virtual void* CurrentItem();
};
Iterator *ConcreteAggregate::CreateIterator()
{
return new ConcreteIterator(this);
}
int ConcreteAggregate::getCount() const
{
return items.size();
}
void *ConcreteIterator::First()
{
return *(*ca)[0];
}
void *ConcreteIterator::Next()
{
if(current < ca->getCount()){
current++;
}
if(current < ca->getCount()){
return *(*ca)[current];
}
return nullptr;
}
bool ConcreteIterator::IsDone()
{
return current >= ca->getCount()?true:false;
}
void *ConcreteIterator::CurrentItem()
{
return *(*ca)[current];
}
class ConcreteIteratorDesc:public Iterator
{
public:
ConcreteAggregate *ca;
int current;
ConcreteIteratorDesc(ConcreteAggregate *c):ca(c){
this->current = c->getCount() - 1;
}
virtual void* First();
virtual void* Next();
virtual bool IsDone();
virtual void* CurrentItem();
};
void *ConcreteIteratorDesc::First()
{
if(ca->getCount() == 0){
return nullptr;
}
return *(*ca)[ca->getCount() - 1];
}
void *ConcreteIteratorDesc::Next()
{
if(current >= 0){
current--;
}
if(current >= 0){
return *(*ca)[current];
}
return nullptr;
}
bool ConcreteIteratorDesc::IsDone()
{
return current < 0?true:false;
}
void *ConcreteIteratorDesc::CurrentItem()
{
return *(*ca)[current];
}
int main()
{
ConcreteAggregate ca;
*(ca[0]) = (void*)5;
*ca[1] = (void*)10;
*ca[2] = (void*)15;
*ca[3] = (void*)20;
// cout << (int) *ca[0] << endl;
// cout << (int) *ca[1] << endl;
// cout << ca.getCount() << endl;
Iterator *i = new ConcreteIterator(&ca);
cout << "开始遍历" << endl;
while(!i->IsDone()){
cout << (int)i->CurrentItem() << endl;
i->Next();
}
Iterator *i_desc = new ConcreteIteratorDesc(&ca);
cout << "开始反向遍历" << endl;
while(!i_desc->IsDone()){
cout << (int)i_desc->CurrentItem() << endl;
i_desc->Next();
}
cout << "--end--" << endl;
return 0;
}
运行结果:
开始遍历
5
10
15
20
开始反向遍历
20
15
10
5
--end--