**20.迭代器模式(Iterator)

意图:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

上下文:集合对象内部结构常常变化各异。对于这些集合对象,能否在不暴露其内部结构的同时,让外部Client透明地访问其中包含的元素,同时让这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供可能?

UML

在这里插入图片描述

Iterator:定义访问和遍历元素的接口(.NET中定义了标准的IEnumrator接口)。ConcreteIterator:实现Iterator接口,同时在对Aggregate遍历时跟踪当前的位置。Aggregate:定义创建相应Iterator对象的接口(.NET中定义了标准的IEnumrable接口)。ConcreteAggregate:实现创建相应Iterator对象的接口,该操作返回一个适当的ConcreteIterator实例。

注意:.NET中的foreach关键字在编译时会自动创建迭代器对象,并使用该对象对集合进行遍历。.NET中的yield return关键字使得定义迭代器对象更加容易。

代码

#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--