迭代器模式-C++实现

题外话:

设计模式是在1994年提出的,当时还没有C++的STL库和泛型编程,所以人们为了提供一种有效的方法来访问一个聚合对象(例如列表、集合、数组等)中的元素,而又不暴露该对象的内部表示,于是想到了迭代器模式。

但随着1998年STL库的诞生,我们知道STL里的容器都是支持迭代器遍历,在这样的情况下我们再使用传统的迭代器模式去遍历元素效率就会很慢。

因为传统的迭代器模式是多态的形式,也就是运行时多态,运行时多态我们需要去访问虚函数表找到要执行的函数地址,在这种情况下当我们的元素有一百万个时,遍历元素就会很慢,完全没必要。

但是虽然设计已经过时,思想却值得我们去学习。

迭代器模式是一种行为型设计模式,它提供了一种有效的方法来访问一个聚合对象(例如列表、集合、数组等)的元素,而不暴露该对象的内部表示。

迭代器模式包含以下四个角色:

1、抽象迭代器:定义迭代聚合对象的接口,提供方法用于获取下一个元素、判断是否还有元素等。

2、具体迭代器:实现抽象迭代器的接口,负责管理迭代的状态,例如当前位置、下一个元素等。

3、抽象聚合对象:定义一个迭代器工厂方法,用于创建一个具体迭代器的实例。

3、具体聚合对象:实现聚合对象接口,返回一个具体迭代器实例。

举例:

c 复制代码
#include <iostream>
#include <memory>
#include <vector>

// 抽象迭代器
template<class T>
class Iterator
{
public:

	virtual ~Iterator() {}

	// 获取下一个元素
	virtual T Next() = 0;

	// 判断是否还有元素
	virtual bool Empty() = 0;
};

// 具体迭代器
template<class T>
class ConcreteIterator
	: public Iterator<T>
{
public:

	ConcreteIterator(const std::vector<T>& _col)
	{
		idx_ = 0;
		data_ = _col;
	}

	virtual T Next() override
	{
		return data_[idx_++];
	}

	virtual bool Empty() override
	{
		return idx_ >= data_.size();
	}

private:

	// 当前位置
	int idx_;

	// 数据
	std::vector<T> data_;
};

// 抽象聚合对象
template<class T>
class Aggregate
{
public:

	virtual ~Aggregate() {}

	virtual void PushBack(const T& _val) = 0;

	virtual std::shared_ptr<Iterator<T>> CreateIterator() = 0;
};

// 具体聚合对象
template<class T>
class ConcreteAggregate
	: public Aggregate<T>
{
public:

	virtual void PushBack(const T& _val) override
	{
		data_.emplace_back(_val);
	}

	virtual std::shared_ptr<Iterator<T>> CreateIterator() override
	{
		return std::make_shared<ConcreteIterator<T>>(data_);
	}

private:

	std::vector<T> data_;
};

在代码中,我们定义了一个Iterator接口,其中包含了Next()和Empty()方法,分别用于获取下一个元素的数据和判断是否还有下一个元素。然后我们实现了一个ConcreteIterator类作为具迭代器的具体实现,它使用了一个std::vector作为聚合对象的集合,并通过追踪当前位置来实现迭代功能。

接下来,我们定义了一个Aggregate接口,其中包含了PushBack()和CreateIterator方法,用于插入元素和创建迭代器。然后实现了一个ConcreteAggregate类作为具体聚合对象的实现,它使用一个std::vector作为数据集合,并且在CreateIterator()方法中返回了一个具体迭代器对象。

测试:

c 复制代码
void TestIterator()
{
	// 创建一个聚合对象
	std::shared_ptr<Aggregate<int>> aggregate = std::make_shared<ConcreteAggregate<int>>();

	// 插入数据
	aggregate->PushBack(1);
	aggregate->PushBack(2);
	aggregate->PushBack(3);
	aggregate->PushBack(4);
	aggregate->PushBack(5);

	// 创建迭代器
	std::shared_ptr<Iterator<int>> iterator = aggregate->CreateIterator();

	// 遍历元素输出
	while (!iterator->Empty())
		std::cout << iterator->Next() << " ";

	std::cout << std::endl;
}

测试代码中,我们创建一个聚合对象,并插入了5个元素,然后又创建了一个迭代器的对象,通过迭代器遍历元素并输出。

输出结果:

c 复制代码
1 2 3 4 5

从上面的例子我们也能看出,迭代器模式其实和STL中的迭代器是一模一样的,不一样的是泛型编程中迭代器是编译时多态,而迭代器模式下是运行时多态,迭代器模式下遍历元素调用的函数需要通过虚函数表去查找函数地址,当元素太多时消耗的资源太多,对现在的C++编程来说已经不适用了。

总结:

1、迭代抽象:访问一个聚合对象的内容而无需暴露它的内部展示。

2、迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

3、迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

相关推荐
kyle~6 小时前
机器视觉---熔池相机(穿透强光的视觉感知)
c++·数码相机·计算机视觉·机器人·焊接机器人
宏笋6 小时前
C++ Coroutines(协程) 详解
c++
王老师青少年编程7 小时前
csp信奥赛C++高频考点专项训练之前缀和&差分 --【一维前缀和】:求区间和
c++·前缀和·csp·高频考点·信奥赛·求和区间和
kyle~7 小时前
机器人时间链路---工程流程示例
c++·3d·机器人·ros2
汉克老师9 小时前
GESP6级C++考试语法知识(十七、数据结构(三、认识队列 Queue))
数据结构·c++·队列·gesp6级·gesp六级·数组模拟队列
j_xxx404_11 小时前
Linux进程信号捕捉与操作系统运行本质深度解析
linux·运维·服务器·开发语言·c++·人工智能·ai
vx-程序开发11 小时前
基于机器学习的动漫可视化系统的设计与实现-计算机毕业设计源码08339
java·c++·spring boot·python·spring·django·php
啊董dong12 小时前
noi-2026年5月12号小测验
数据结构·c++·算法
咩咦13 小时前
C++学习笔记24:构造函数初始化列表
c++·学习笔记·类和对象·构造函数·初始化列表·const引用
计算机安禾13 小时前
【c++面向对象编程】第43篇:可变参数模板(C++11):优雅处理不定长参数
java·开发语言·c++