S21. 迭代器模式

2022-05-04  本文已影响0人  拂去尘世尘

迭代器模式

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

C++ STL中各个容器都有迭代器的体现,通过迭代器能够顺序的访问该容器各成员。

意义

有利于隐藏聚合类的内部实现,外部通过迭代器来实现对聚合类的顺序访问。

场景

实现聚合类的一种顺序访问。

注: 对于开发者来讲,基本上不会实现一套迭代器。因为现存的标准库都有提供各种容器List、Array等,都有提供迭代器遍历。这里只是简单分析这种模式的实现原理。

类图

迭代器模式-类图.png

注: 为了实现通用的迭代器,迭代器类使用了泛型编程的模板方法。

源码实现

编程环境

  1. 编译环境: Linux环境
  2. 语言: C++语言
  3. 编译命令: make

工程结构

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;
};

客户端代码
测试内容大致为: 定义了一个容器,依次向容器中存放变量,并遍历。

  1. int型容器
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;
}
  1. float容器
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;
}

测试效果

  1. int型:
$ ./exe 
[0]: 1
[1]: 2
[2]: 13

2: float型:

./exe 
[0]: 1.20
[1]: 2.00
[2]: 13.00

通过测试发现,两种类型的容器都可以实现遍历。

总结

上一篇下一篇

猜你喜欢

热点阅读