C++ Iterator设计模式的思考 (Boolan学习笔记第13周)

Iterator设计模式是GOF里面的23中设计模式之一, 其定义是”提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。

在没有学Iterator设计模式之前,如果要遍历容器里面的各个元素,我们可能想到的就是用一个链表把这些元素连起来,然后通过->next来遍历这些元素。但是这样就暴露了容器的内部细节。另外,如果有多个client同时遍历这个容器,可能还要给这个链表加个锁什么的,这样又浪费了系统资源。这些问题的原因都是容器的内部和它的遍历紧耦合了。

Iterator设计模式则把容器的内部实现和它的遍历实现了解耦,其结构图如下:

这里写图片描述

上面的各个部分说明如下:
Iterator:定义迭代器访问和遍历元素的接口;
ConcreteIterator:实现具体的迭代器;
Aggregate:定义的容器,创建相应迭代器对象的接口;
ConcreteAggregate:具体的容器实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例。

一个Iterator设计模式的基本代码如下:

template<typename T>
class Iterator
{
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool isDone() const = 0;
    virtual T& current() = 0;
};

template<typename T>
class MyCollection{

public:

    Iterator<T> GetIterator(){
        //...
    }

};

template<typename T>
class CollectionIterator : public Iterator<T>{
    MyCollection<T> mc;
public:

    CollectionIterator(const MyCollection<T> & c): mc(c){ }

    void first() override {

    }
    void next() override {

    }
    bool isDone() const override{

    }
    T& current() override{

    }
};

void MyAlgorithm()
{
    MyCollection<int> mc;

    Iterator<int> iter= mc.GetIterator();

    for (iter.first(); !iter.isDone(); iter.next()){
        cout << iter.current() << endl;
    }

}

在上面代码中,CollectionIterator就是结构图里面的ConcreteAggregate,里面包含了MyCollection的对象mc。在for loop中,里面的first(),isDone()和next()都是重载后的虚函数,实现运行时绑定。这样,用户并不知道MyCollection的内部细节,也可以实现遍历。

不过我想补充的是Iterator这种设计模式在JAVA里面用的很多,但是在C++里面已经过时了。为什么呢?因为Iterator设计模式是基于虚函数的,属于运行时绑定。我们知道虚函数运行时绑定就要查虚函数表,如果在一个很大的loop里面的话,这种虚函数绑定累计起来就耽误了很多时间,效率非常低。

而C++的STL是采用泛型编程,属于编译时绑定,效率非常高。那么为什么泛型编程可以在编译时绑定呢?因为它是基于Traits实现的,内部用到了类模板和偏特化。所以STL里面的Iterator并不是用的Iterator设计模式!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值