您的位置:首页 > 编程语言 > C语言/C++

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

2017-04-16 05:40 375 查看
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设计模式!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 c++