0. 简介

迭代器模式是一种行为设计模式, 它可以有效管理数据流动的同时,让用户能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。

迭代器通常会提供一个获取集合元素的基本方法。 客户端可不断调用该方法直至它不返回任何内容, 这意味着迭代器已经遍历了所有元素。

1. 迭代器模式示意图

迭代器模式的使用方法和c11的迭代器使用方法类似,这是我们会根据我们的需求去建立迭代器模型。
在这里插入图片描述
抽象容器(Collection):一般是一个接口,提供一个iterator()方法,例如Collection接口,List接口,Set接口等

具体容器(Concrete Collections):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。

抽象迭代器(Iterator):定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove(),

具体迭代器(Concrete Iterators):实现迭代器接口中定义的方法,完成集合的迭代。

2. 示例程序

在迭代器中主要分为两大主要部分:

  1. 容器部分,内部可以存放一系列数据,并提供迭代器调用接口。
  2. 迭代器部分,内部含有对容器部分的调用,并获得容器内部提供的方法。

从下述的图中,我们可以看到具体容器和具体迭代器两者是相互调用的,也就是说容器调用了迭代器,然后通过迭代器调用了容器内部自身的方法来实现封装。
在这里插入图片描述

#include <iostream>
#include <string>
#include <vector>

using namespace std;
/**
* @brief 简单概述
* @brief 迭代器基类
*/
class Iterator
{
public:
    Iterator(){};
    virtual ~Iterator(){};
    virtual string First() = 0;
    virtual string Next() = 0;
    virtual string GetCur() = 0;
    virtual bool IsEnd() = 0;
};
/**
* @brief 简单概述
* @brief 对象基类
*/
class Aggregate
{
public:
    Aggregate(){};
    virtual ~Aggregate(){};
    virtual int Count() = 0;
    virtual void Push(const string &strValue) = 0;
    virtual string Pop(const int index) = 0;
    virtual Iterator *CreateIterator() = 0;
};
/**
* @brief 简单概述
* @brief 迭代器子类
*/
class ConcreteIterator : public Iterator
{
public:
    ConcreteIterator(Aggregate *pAggregate) : Iterator()
    {
        m_nCurrent = 0;
        m_Aggregate = pAggregate;
    }

    string First()
    {
        return m_Aggregate->Pop(0);
    }

    string Next()
    {
        string strRet;
        m_nCurrent++;

        if(m_nCurrent < m_Aggregate->Count())
        {
            strRet = m_Aggregate->Pop(m_nCurrent);
        }

        return strRet;
    }

    string GetCur()
    {
        return m_Aggregate->Pop(m_nCurrent);
    }

    bool IsEnd()
    {
        return ((m_nCurrent >= m_Aggregate->Count()) ? true : false);
    }

private:
    int m_nCurrent;
    Aggregate *m_Aggregate;
};
/**
* @brief 简单概述
* @brief 对象类
*/
class ConcreteAggregate : public Aggregate
{
public:
    ConcreteAggregate() : m_pIterator(NULL)
    {
        m_vecItems.clear();
    }

    ~ConcreteAggregate()
    {
        if(m_pIterator != NULL)
        {
            delete m_pIterator;
            m_pIterator = NULL;
        }
    }

    Iterator *CreateIterator()
    {
        if(m_pIterator == NULL)
        {
            m_pIterator = new ConcreteIterator(this);
        }

        return m_pIterator;
    }

    int Count()
    {
        return m_vecItems.size();
    }

    void Push(const string &strValue)
    {
        m_vecItems.push_back(strValue);
    }

    string Pop(const int index)
    {
        string strRet;

        if(index < Count())
        {
            strRet = m_vecItems[index];
        }

        return strRet;
    }

private:
    Iterator *m_pIterator;
    vector<string> m_vecItems;
};

int main(int argc, char **argv)
{
    ConcreteAggregate *pName = new ConcreteAggregate();
    if(pName == NULL)
        return -1;

    pName->Push("hello");
    pName->Push("world");
    pName->Push("cxue");

    Iterator *iter = NULL;
    iter = pName->CreateIterator();

    if(iter != NULL)
    {
        string strItem = iter->First();

        while(!iter->IsEnd())
        {
            cout << iter->GetCur() << " is ok" << endl;
            iter->Next();
        }
    }   

    delete pName;

    return 0;
}

/**
hello is ok
world is ok
cxue is ok
**/

3. 迭代器之模板类

下面是基于迭代器的两个通用模板类,这样可以有效的降低代码的重复性

using namespace std;

// 迭代基类
template<class Item>

class Iterator
{
public:
    Iterator() {};
    virtual ~Iterator() {};

    virtual void first() = 0;
    virtual void next() = 0;
    virtual Item *curItem() = 0;
    virtual bool isDone() = 0;
};

// 迭代具体类
template<class Item>

class ConcreteIterator : public Iterator <Item>
{
public:
    ConcreteIterator(Aggregate<Item> *a) :aggr(a), cur(0) {};
    virtual ~ConcreteIterator() {};

    virtual void first();
    virtual void next();
    virtual Item *curItem();
    virtual bool isDone();
private:
    Aggregate<Item> *aggr;
    int cur;
};

template<class Item>
void ConcreteIterator<Item>::first()
{
    cur = 0;
}

template<class Item>
void ConcreteIterator<Item>::next()
{
    if (cur < aggr->getSize())
        cur++;
}

template<class Item>
Item *ConcreteIterator<Item>::curItem()
{
    if (cur < aggr->getSize())
    {
        return &(*aggr)[cur];
    }
    else
    {
        return NULL;
    }
}

template<class Item>
bool ConcreteIterator<Item>::isDone()
{
    return cur >= aggr->getSize();
}

// 容器基类
template<class Item>
class Aggregate{
public:
    Aggregate() {};
    virtual ~Aggregate() {};

    virtual void pushData(Item item) = 0;
    virtual Iterator<Item>* createIterator() = 0;
    virtual Item& operator[](int index) = 0;
    virtual int getSize() = 0;
};              
// 容器具体类

template <class Item>
class ConcreteAggregate : public Aggregate<Item>
{
public:
    ConcreteAggregate() {};
    virtual ~ConcreteAggregate() {};

    virtual void pushData(Item item);
    virtual Iterator<Item>* createIterator();
    virtual Item& operator[](int index);
    virtual int getSize();
private:
    vector<Item> data;
};

template <class Item>
void ConcreteAggregate<Item>::pushData(Item item)
{
    data.push_back(item);
}

template <class Item>
Iterator<Item>* ConcreteAggregate<Item>::createIterator()
{
    return new ConcreteIterator<Item>(this);
}

template <class Item>
Item& ConcreteAggregate<Item>::operator[](int index)
{
    return data[index];
}

template <class Item>
int ConcreteAggregate<Item>::getSize()
{
    return data.size();
}

/** main 函数
int main(int argc, char *argv[])
{

    Aggregate<int> * aggr = new ConcreteAggregate<int>();
    aggr->pushData(3);
    aggr->pushData(2);
    aggr->pushData(1);
    Iterator<int> * it = aggr->createIterator();

    for (it->first(); !it->isDone(); it->next())
    {
        std::cout << *it->curItem() << std::endl;
    }
    delete it;
    delete aggr;
}
**/

这里涉及到两个class如果不用基类相互调用的时,那就需要使用友元来相互调用了

#include <iostream>
#include <string>
#include <vector>

template <typename T, typename U>
class Iterator {
 public:
  typedef typename std::vector<T>::iterator iter_type;
  Iterator(U *p_data, bool reverse = false) : m_p_data_(p_data) {
    m_it_ = m_p_data_->m_data_.begin();
  }

  void First() {
    m_it_ = m_p_data_->m_data_.begin();
  }

  void Next() {
    m_it_++;
  }

  bool IsDone() {
    return (m_it_ == m_p_data_->m_data_.end());
  }

  iter_type Current() {
    return m_it_;
  }

 private:
  U *m_p_data_;
  iter_type m_it_;
};


template <class T, typename U>
class Iterator<T, U>;    //声明类
class Container {
  friend class Iterator<T, Container>;//把Iterator声明成友元类

 public:
  void Add(T a) {
    m_data_.push_back(a);
  }

  Iterator<T, Container> *CreateIterator() {
    return new Iterator<T, Container>(this);
  }

 private:
  std::vector<T> m_data_;
};

class Data {
 public:
  Data(int a = 0) : m_data_(a) {}

  void set_data(int a) {
    m_data_ = a;
  }

  int data() {
    return m_data_;
  }

 private:
  int m_data_;
};

int main() {
  Container<int> cont;

  for (int i = 0; i < 10; i++) {
    cont.Add(i);
  }

  Iterator<int, Container<int>> *it = cont.CreateIterator();
  for (it->First(); !it->IsDone(); it->Next()) {
    std::cout << *it->Current() << std::endl;
  }

  Container<Data> cont2;
  Data a(100), b(1000), c(10000);
  cont2.Add(a);
  cont2.Add(b);
  cont2.Add(c);

  Iterator<Data, Container<Data>> *it2 = cont2.CreateIterator();
  for (it2->First(); !it2->IsDone(); it2->Next()) {
    std::cout << it2->Current()->data() << std::endl;
  }
  delete it;
  delete it2;
  return 0;
}

4. 迭代器的优缺点

在这里插入图片描述
迭代器可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。同时其封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心

当然随之带来的就是繁琐,对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐。

5. 参考链接

https://zhuanlan.zhihu.com/p/323212207

https://refactoringguru.cn/design-patterns/iterator

https://blog.csdn.net/u012611878/article/details/78010435