博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c++设计模式:迭代器模式(Iterator Pattern)

Posted on 2012-02-09 15:35  开源云  阅读(1354)  评论(0编辑  收藏  举报

定义:迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

场景:我们有两个聚合A和B,有一个聚合管理的类,包含聚合A和B,而这个管理类的功能就是依次遍历它所包含的聚合中的元素并打印到控制台上。每个聚合中的元素存放的方式是不同的,有的用的是数组,有的可能是vector或者list等,因此我么为每个聚合定义了一个迭代器,管理类只需要依次获取各聚合的迭代器,使用迭代器去遍历其中的元素,而不需要去理会聚合中元素的存放方式。

类图:

c++代码如下:

#include <iostream>
#include <vector>
using namespace std;

#define COUNT 5

class Iterator
{
public:
virtual bool hasNext() = 0;
virtual int next() = 0;
};

class Menu
{
public:
virtual Iterator* createIterator() = 0;
};

class CAggregateAIter : public Iterator
{
public:
CAggregateAIter(vector<int> vData);
bool hasNext();
int next();
private:
vector<int> m_vData;
int m_iPosition;
};

class CAggregateBIter : public Iterator
{
public:
CAggregateBIter(int* piData);
bool hasNext();
int next();
private:
int m_iPosition;
int m_iData[COUNT];
};

class CAggregateA : public Menu
{
public:
CAggregateA();
Iterator* createIterator();
private:
vector<int> m_vData;
};

class CAggregateB : public Menu
{
public:
CAggregateB();
Iterator* createIterator();
private:
int m_iData[COUNT];
};

class AggregateMg
{
public:
void printAggr();
void printAggr(Iterator* piter);
private:
CAggregateA m_aggrA;
CAggregateB m_aggrB;
};

CAggregateAIter::CAggregateAIter(vector<int> vData)
{
m_iPosition = 0;
for (int i=0; i<vData.size(); ++i)
{
m_vData.push_back(vData.at(i));
}
}
bool CAggregateAIter::hasNext()
{
if (m_iPosition < m_vData.size())
{
return true;
}
else
{
return false;
}
}
int CAggregateAIter::next()
{
int iData = m_vData.at(m_iPosition);
++m_iPosition;
return iData;
}

CAggregateBIter::CAggregateBIter(int* piData)
{
m_iPosition = 0;
for (int i=0; i<COUNT; ++i)
{
m_iData[i] = piData[i];
}
}
bool CAggregateBIter::hasNext()
{
if (m_iPosition < COUNT)
{
return true;
}
else
{
return false;
}
}
int CAggregateBIter::next()
{
int iData = m_iData[m_iPosition];
++m_iPosition;
return iData;
}

CAggregateA::CAggregateA()
{
for (int i=0; i<COUNT; ++i)
{
m_vData.push_back(i*(i+1));
}
}
Iterator* CAggregateA::createIterator()
{
return new CAggregateAIter(m_vData);
}

CAggregateB::CAggregateB()
{
for (int i = 0; i < COUNT; ++i)
{
m_iData[i] = i*(i+1);
}
}
Iterator* CAggregateB::createIterator()
{
return new CAggregateBIter(m_iData);
}

void AggregateMg::printAggr()
{
Iterator* piter1 = m_aggrA.createIterator();
Iterator* piter2 = m_aggrB.createIterator();
printAggr(piter1);
printAggr(piter2);
delete piter1;
delete piter2;
}

void AggregateMg::printAggr(Iterator* piter)
{
while(piter->hasNext())
{
printf("%d\n",piter->next());
}
}

int main()
{
AggregateMg aggrMg;
aggrMg.printAggr();
return 0;
}

运行结果如下:

0
2
6
12
20
0
2
6
12
20

 

解释:

1、我们使用c++ STL的时候常用的迭代器方法是begin(),end()等。有些迭代器提供的是first(),isDone(),currentItem()等方法,其实怎么封装,最终实现的都是迭代器模式定义中的不暴露聚合内部的表示,让迭代器来实现顺序访问聚合中元素的功能,我们甚至可以为迭代器封装一些操作聚合元素的方法,例如remove()。

2、我们将聚合管理类与各个聚合类之间解耦了,如果我们为聚合管理类新加了一些其它的聚合,那么我们只需要修改很少的代码就可以完成我们的工作,而且不会影响其它的功能。

 

参考图书:《Head First 设计模式》