771-C++设计模式 - 迭代器模式

本文介绍了迭代器模式的概念,它提供了一种在不暴露容器内部结构的情况下顺序访问容器元素的方法。迭代器模式的UML类图及基本接口如文中所示。接着,通过C++代码示例展示了如何在CArray类中实现迭代器,以及如何使用迭代器遍历容器。最后,将C++STL的容器迭代器与通用迭代器模式进行了对比,强调了两者在设计上的相似性和差异。
摘要由CSDN通过智能技术生成

迭代器模式简介

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

先给出迭代器模式的一个UML类图设计如下:
在这里插入图片描述
所以一个迭代器最基本应该提供下面这几个接口操作,代码如下:

#include<iostream>

using namespace std;

//迭代器的抽象基类
template<typename _Ty>
class Iterator
{
public:
	//是否还有下一个元素
	virtual bool hasNext() = 0;
	//返回下一个元素
	virtual _Ty& next() = 0;
};

上面定义了一个迭代器的抽象基类
hasNext接口表示聚合对象(也就是容器)内部是否还有下一个元素,next接口返回下一个元素的值引用,通过这样的一个迭代器实例遍历访问容器的内部元素,不需要知道容器内部的具体实现,对于用户来说,完全是透明的。

当然不同的容器,由于其内部数据结构不同,迭代器遍历它们的方式也就不同了,因此迭代器一般设计为容器的嵌套类,直接在容器内部实现迭代器迭代的逻辑过程,请看下面的代码示例

迭代器模式代码示例

看如下代码示例:

#include<iostream>

using namespace std;

//迭代器的抽象基类
template<typename _Ty>
class Iterator
{
public:
	//是否还有下一个元素
	virtual bool hasNext() = 0;
	//返回下一个元素
	virtual _Ty& next() = 0;
};

//容器类的定义
template<typename _Ty>
class CArray
{
public:
	//只提供了容器添加元素的操作
	template<typename _Ty>
	void push(_Ty&& val)
	{
		_vec.push_back(std::forward<_Ty>(val));
	}

	//当前容器迭代器的实现
	class ConcreteIterator : public Iterator<_Ty>
	{
	public:
		//迭代器的构造函数
		ConcreteIterator(CArray<_Ty>& arr)
			:_array(arr)
		{
			_cur = 0;
		}

		//判断是否还有下一个元素
		bool hasNext()
		{
			int size = _array._vec.size();
			return _cur < size;
		}

		//返回下一个元素的值
		_Ty& next()
		{
			_Ty& val = _array._vec[_cur];
			_cur++;
			return val;
		}
	private:
		CArray<_Ty>& _array;//获取当前迭代器所迭代器的容器的引用
		int _cur;//当前迭代器的元素下标
	};

	//返回容器的迭代器的函数接口
	Iterator<_Ty>* createIterator()
	{
		return new ConcreteIterator(*this);
	}
private:
	vector<_Ty> _vec;//存储元素的容器
};

CArray在这里作为一个容器的实现,它底层直接使用vector容器作为元素的存储结构,其内部实现了一个迭代器ConcreteIterator,从Iterator继承而来,重写了hasNext和next两个方法,作为具体的遍历CArray容器的迭代器,又提供了一个createIterator函数,专门返回该容器对象的迭代器,具体遍历的代码如下:

int main()
{
	//定义容器对象
	CArray<int> array;
	//添加右值参数
	array.push(20);
	array.push(56);
	array.push(3);
	array.push(21);
	//添加左值参数
	int data = 89;
	array.push(89);

	//用迭代器遍历访问容器对象内部的元素并打印
	Iterator<int>* it = array.createIterator();
	while (it->hasNext())
	{
		int val = it->next();
		cout << val << " ";
	}
	cout << endl;

	return 0;
}

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

熟悉C++ STL容器内部迭代器设计的人都知道,STL容器迭代器的设计和上面通用迭代器模式本质相同,实现细节上还是有一些区别,下面做一下对比。

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

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

下面演示一个C++STL容器迭代器的标准使用方式,代码示例如下:

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值