设计模式笔记:迭代器模式

设计模式简单来说就是在解决某一类问题场景时,有既定的,优秀的代码框架可以直接使用

迭代器模式Iterator的核心功能,就是提供了一种特定的方法,顺序访问一个容器中的各个元素,既不会暴露容器的内部设计细节(容器底层数据结构),又可以让外部代码访问集合内部的所有元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <vector>
using namespace std;
// 迭代器的抽象基类
template<typename T>
class Iterator {
public:
// 是否还有下一个元素
virtual bool HasNext() = 0;
// 返回下一个元素
virtual T& Next() = 0;
};

// 容器类的定义
template<typename T>
class MyAarry
{
public:
// 只提供了容器添加元素的操作
void Push(T&& value)
{
vec_.push_back(std::forward<T>(value));
}

// 当前容器迭代器的实现
class ConcreteIterator : public Iterator<T> {
public:
ConcreteIterator(MyAarry<T>& array) : _array(array) {
curIndex = 0;
}

bool HasNext()
{
int size = _array.vec_.size();
if (curIndex < size) {
return true;
}
return false;
}
T& Next()
{
T& val = _array.vec_[curIndex];
curIndex++;
return val;
}

private:
MyAarry<T>& _array;
int curIndex;
};

// 返回容器的迭代器的函数接口
Iterator<T>* CreateIterator()
{
return new ConcreteIterator(*this);
}

private:
vector<T> vec_; // 存储元素的容器
};

int main()
{
// 定义容器对象
MyAarry<int> array;
array.Push(7); // 添加右值参数
array.Push(9);
array.Push(5);
array.Push(66);
array.Push(11);

// 添加左值参数

// 用迭代器遍历访问容器对象内部的元素并打印
Iterator<int>* it = array.CreateIterator();
while(it->HasNext()) {
cout << it->Next() << endl;
}
return 0;
}

上面main函数中,迭代器遍历访问容器的代码就是通用的代码,不论容器底层数据结构怎么变化,迭代器遍历容器的方式不会改变,其底层差异细节完全封装在了迭代器的hasNext和next函数中,对于用户来说内部操作完全是透明的

C++ STL的容器迭代器设计

C++ STL内部的容器迭代器和上面通用迭代器模式的设计类比:

迭代器设计成容器的嵌套类型,因为不同的容器由于其底层数据结构的不同,需要为每个容器实现自己的迭代器进行具体的数据遍历。
C++STL容器统一提供begin()和end()方法返回容器起始元素的迭代器和末尾元素后继位置的迭代器,类比上面CArray容器提供的createIterator方法。
C++STL的迭代器通过和容器的end()相比较来判断容器元素是否迭代完成,类比上面通用迭代器的hasNext方法。
C++STL的迭代器把容器内部数据遍历的细节封装在了迭代器的operator++运算符重载函数里面,并提供迭代器的operator*()运算符重载函数,访问迭代器遍历的元素的值,类比上面通用迭代器的next方法的功能。
下面演示一个C++STL容器迭代器的标准使用方式,代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
// 定义vector容器对象,添加20个随机整数
vector<int> vec;
srand(time(nullptr));
for (int i = 0; i < 20; ++i)
{
vec.push_back(rand() % 100 + 1);
}

// 通过vector容器的迭代器遍历访问容器的所有元素
vector<int>::iterator it = vec.begin();
for (; it != vec.end(); ++it)
{
cout << *it << " ";
}
cout << endl;

// C++11提供了新的容器遍历语法foreach,其底层就是通过迭代器来实现的
for (int val : vec)
{
cout << val << " ";
}
cout << endl;

return 0;

}