迭代器模式在容器类中经常使用,该模式可以解决两个问题:第一个问题,处于面向对象封装特性的考虑,我们希望程序员尽可能不获取容器的私有数据就能够遍历所有的数据,但是有希望能够提供一个接口,供程序员获取所有的私有数据,因此可以借助迭代器辅助容器类进行数据的访问;第二个问题,在C++中提供了vector、map以及list等容器,他们的提供了不同的方法让程序员去遍历容器中的所有数据,这显然增加了程序员去熟记不同方法的代价,那么能不能给这些容器提供一个统一的接口,从而实现一个接口比遍历不同容器的功能呢?迭代器模式就能解决上述两个问题。
如上图所示,对于一个Container类,为了给程序员提供一个访问其内部数据的接口,可在Container类中创建一个内部类,通过这个内部类抽象的方法来实现遍历各种不同的内部类的数据的功能。
1. 迭代器抽象类
在迭代器抽象类中主要抽象出了hasNext()方法以及next()方法,前者用于判断容器中当前访问的数据后面还有没有剩余的数据,而next()方法则返回当前指针的数据并移动到下一个数据。
#include <iostream>
#include <vector>
using namespace std;
template<typename _type>
class Iterator{
public:
virtual bool hasNext() = 0;
virtual const _type& next() = 0;
};
2. 具体容器类与具体迭代器类
具体迭代器类是具体容器类的内部类。外部类与内部类是两个独立的类,也就是说外部类不能够直接获取内部类的数据,内部类也不能够直接使用内部类的数据。如果内部类需要访问外部类的数据,就需要将外部类作为内部类的一个成员变量。
为了获取容器类的内部迭代器类,就需要让外部类提供了接口,返回内部类的指针,这样就能够实现通过迭代器访问容器类数据的功能了。
template<typename _type>
class Container{
private:
vector<_type> container;
int idx, volume;
public:
// 内部迭代类,用于管理内存
class ConcertIterator:public Iterator<_type>{
private:
int idx, volume;
const Container* pc;
public:
ConcertIterator():pc(nullptr),idx(0),volume(0){};
ConcertIterator(const Container* pc):pc(pc),idx(0),volume(pc->volume){};
~ConcertIterator(){};
bool hasNext(){
return idx < volume;
}
const _type& next(){
return pc->container[idx++];
}
};
public:
Container():idx(0), volume(10){};
Container(const int v):idx(0), volume(v){};
~Container(){};
void attach(const _type& value){
if(idx>=volume){
return;
}
container.push_back(value);
++idx;
}
// 获得迭代器
ConcertIterator* getIterator(){
return new ConcertIterator(this);
}
};
3. 实验结果
下面是具体的测试代码以及实验结果:
int main(){
Container<int>* container = new Container<int>(5);
for(int i = 0; i < 5; ++i){
// 向容器中添加数据
container->attach(i);
}
Iterator<int>* it = container->getIterator();
// 遍历容器中所有的数据
while(it->hasNext()){
cout << it->next() << endl;
}
return 0;
}