C++之迭代器(Iterator)模式
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. 示例程序
在迭代器中主要分为两大主要部分:
- 容器部分,内部可以存放一系列数据,并提供迭代器调用接口。
- 迭代器部分,内部含有对容器部分的调用,并获得容器内部提供的方法。
从下述的图中,我们可以看到具体容器和具体迭代器两者是相互调用的,也就是说容器调用了迭代器,然后通过迭代器调用了容器内部自身的方法来实现封装。
#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;
}
…详情请参照古月居
- 点赞
- 收藏
- 关注作者
评论(0)