前言
你的坚持,终将美好!
❝提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。 ❞
C++ STL中各个容器都有迭代器的体现,通过迭代器能够顺序的访问该容器各成员。
有利于隐藏聚合类的内部实现,外部通过迭代器来实现对聚合类的顺序访问。
实现聚合类的一种顺序访问。
注: 对于开发者来讲,基本上不会实现一套迭代器。因为现存的标准库都有提供各种容器List、Array等,都有提供迭代器遍历。这里只是简单分析这种模式的实现原理。
迭代器模式类图
注: 为了实现通用的迭代器,迭代器类使用了泛型编程的模板方法。
「编程环境」
「工程结构」
Iterator/
├── aggregatebase.h
├── aggregate.h
├── iteratorbase.h
├── iterator.h
├── main.cc
└── Makefile
「迭代器实现」
template<typename T>
class CIterator : public CIteratorBase <T>
{
public:
CIterator(CAggregate<T>* aggregate) : mIndex(0), mAgg(aggregate)
{
}
~CIterator()
{
if (NULL != mAgg) {
delete mAgg;
}
}
T* First()
{
mIndex = 0;
if (mAgg->mData[0]) {
return &mAgg->mData[0];
} else {
ITER_LOGE("mAgg is NULL!\n");
return NULL;
}
}
T* Next()
{
mIndex++;
if (mIndex < mAgg->mData.size()) {
return &mAgg->mData[mIndex];
} else {
ITER_LOGD("mAgg is NULL!\n");
return NULL;
}
}
T *CurPos()
{
if (mAgg->mData[mIndex]) {
return &mAgg->mData[mIndex];
} else {
ITER_LOGE("mAgg is NULL!\n");
return NULL;
}
}
bool IsEnd()
{
if (mIndex < mAgg->mData.size()) {
return true;
} else {
ITER_LOGD("mIndex[%d] Size[%ld]\n", mIndex, mAgg->mData.size());
return false;
}
}
private:
unsigned int mIndex;
CAggregate<T> *mAgg;
};
「聚合类实现」
template <typename T>
class CAggregate : public CAggregateBase<T>
{
friend class CIterator <T>;
public:
CAggregate() : mIterator(NULL)
{
}
~CAggregate()
{
if (mIterator) {
delete mIterator;
}
}
void push_back(T data)
{
mData.push_back(data);
}
private:
std::vector<T> mData;
CIteratorBase<T>* mIterator;
};
「客户端代码」 测试内容大致为: 定义了一个容器,依次向容器中存放变量,并遍历。
int main(int argc, char *argv[])
{
int i = 0;
CAggregate<int> *agg = new CAggregate<int>();
CIterator<int> it(agg);
agg->push_back(1);
agg->push_back(2);
agg->push_back(13);
for (it.First(); it.IsEnd(); it.Next())
{
printf("[%d]: %d\n", i, *it.CurPos());
i++;
}
return 0;
}
int main(int argc, char *argv[])
{
int i = 0;
CAggregate<float> *agg = new CAggregate<float>();
CIterator<float> it(agg);
agg->push_back(1.2);
agg->push_back(2);
agg->push_back(13);
for (it.First(); it.IsEnd(); it.Next())
{
printf("[%d]: %0.2f\n", i, *it.CurPos());
i++;
}
return 0;
}
$ ./exe
[0]: 1
[1]: 2
[2]: 13
2: float型:
./exe
[0]: 1.20
[1]: 2.00
[2]: 13.00
通过测试发现,两种类型的容器都可以实现遍历。
用心感悟,认真记录,写好每一篇文章,分享每一框干货。
更多文章内容包括但不限于C/C++、Linux、开发常用神器等,可进入“开源519公众号”聊天界面输入“文章目录” 或者 菜单栏选择“文章目录”查看。公众号后台聊天框输入本文标题,在线查看源码。