C++设计模式行为模式———迭代器模式

news/2024/11/24 0:52:58/

文章目录

一、引言

迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。C++标准库中内置了很多容器并提供了合适的迭代器,尽管我们不需要实现迭代器,但是需要了解迭代器的设计理念。


二、迭代器模式

我们设计一个固定大小数组作为容器,并实现一个迭代器。首先创建一个抽象迭代器:

template<class T>
class myIter{
public:virtual void First() = 0;virtual void Next() = 0;//指向下一个元素virtual bool IsDone() = 0;//是否遍历完virtual T& CurrentItem() = 0;//获取当前的元素virtual ~myIter() {}//作父类时析构函数应该为虚函数
};

上述迭代器仅有四个接口,这4个接口一般被认为是选代器应该实现的最小接口。当然,也可以根据实际需要,增加更多的接口。接着,创建一个抽象容器:

template<class T>
class myContainer{
public:
public:virtual myIter<T>* CreateIterator() = 0;//创建选代器virtual T& getItem(int index) = 0;//获取当前元素virtual int getSize() = 0;//容器中元素数量virtual ~myContainer() {}//作父类时析构函数应该为虚函数
};

从上面的代码中可以看到,为了支持所谓的多态迭代,在抽象容器类模板中定义了一个CreateIterator接口(成员函数),后续在具体的容器子类模板中,会在该接口中运用工厂模式创建相应的选代器。

template<class T>
class myVectorIter :public myIter<T>
{
public:myVectorIter(myContainer<T>*tmpc) :myvector(tmpc){m_current = 0;}virtual void First(){m_current = 0;//容器(数组)中的第一个元素下标为0}	virtual void Next(){m_current++;//下标+1,意味着数组中的下一个元素}virtual bool IsDone(){if (m_current >= myvector->getSize())return true;return false;}virtual T& CurrentItem(){return myvector->getItem(m_current);}
private:myContainer<T>* myvector;int m_current;//记录数组的当前下标(选代器在当前容器中的位置)
};

最后来一个具体的容器:

//具体容器类模板
template<typename T>
class myVector :public myContainer<T>{
public:myVector()//将数组中元素进行初始化{for (int i = 0; i < 10; ++i)m_elem[i] = i;}virtual myIter<T>* CreateIterator(){return new myVectorIter<T>(this);//要考虑在哪里释放的问题}virtual T& getItem(int index){return m_elem[index];}virtual int getSize(){return 10;//为简化代码,返回固定数字}
private://为了简化代码,将容器实现为固定装人10个元素的数组T m_elem[10];
};

在上述代码中,CreateIterator接口使用了工厂模式来创建一个具体的选代器,从而实现了多态选代(这意味着可以增加创建其他选代器的接口来支持不同的送代器,例如,再支持一个反向选代器来从最后一个元素向前遍历等)。

myContainer<int>* pcon = new myVector<int>();
myIter<int>* iter = pcon->CreateIterator();
for (iter->First(); !iter->IsDone(); iter->Next())
{cout << iter->CurrentItem() << endl;
}

代码可以看到,我们的迭代器完成了对容器的遍历。

在这里插入图片描述

迭代器模式一般包含四个角色:

  • 抽象迭代器Iterator):用于定义访问和遍历容器中的元素接口。
  • 具体迭代器ConcreteIterator):实现了抽象迭代器的接口,完成对聚合对象的元素遍历,记录当前元素的位置。
  • 抽象聚合Aggregate):将聚合理解为容器,用于存储和管理元素对象,声明一个CreateIterator方法用于创建一个迭代器对象,充当创建迭代器的工厂角色
  • 具体聚合ConcreteAggregate):实现了抽象的CreateIterator方法以创建相应的迭代器,该方法返回ConcreteAggregate的一个是适当的实例。

迭代器模式结构

在这里插入图片描述

迭代器模式做到了在不暴露内部结构的情况下,让外部代码透明地遍历(访问)其中包含元素的效果,另外值得一提的是,虽然不同的容器内部实现方式不同,但是通过迭代器来访问它们的方式却相同。

引入迭代器设计模式的定义:提供一种方法顺序访问一个聚合对象(容器)中各个元素,而又不暴露该对象的内部表示。

迭代器模式的核心思想就是把容器中对元素访问的代码放人迭代器中实现,与容器本身的功能代码相分离(容器是一个对象,迭代器是另一个对象),从而简化容器的设计。容器和迭代器之间彼此独立,从而使整个系统的设计更加灵活,可以定义不同的迭代器实现不同的遍历策略,例如常规迭代器、反向迭代器、const迭代器等都可以分别实现。


三、总结

当集合背后为复杂的数据结构, 且你希望对客户端隐藏其复杂性时 (出于使用便利性或安全性的考虑), 可以使用迭代器模式。迭代器封装了与复杂数据结构进行交互的细节, 为客户端提供多个访问集合元素的简单方法。 这种方式不仅对客户端来说非常方便, 而且能避免客户端在直接与集合交互时执行错误或有害的操作, 从而起到保护集合的作用。

使用方法:

  1. 声明迭代器接口。 该接口必须提供至少一个方法来获取集合中的下个元素。 但为了使用方便, 你还可以添加一些其他方法, 例如获取前一个元素、 记录当前位置和判断迭代是否已结束。
  2. 声明集合接口并描述一个获取迭代器的方法。 其返回值必须是迭代器接口。 如果你计划拥有多组不同的迭代器, 则可以声明多个类似的方法。
  3. 为希望使用迭代器进行遍历的集合实现具体迭代器类。 迭代器对象必须与单个集合实体链接。 链接关系通常通过迭代器的构造函数建立。
  4. 在你的集合类中实现集合接口。 其主要思想是针对特定集合为客户端代码提供创建迭代器的快捷方式。 集合对象必须将自身传递给迭代器的构造函数来创建两者之间的链接。
  5. 检查客户端代码, 使用迭代器替代所有集合遍历代码。 每当客户端需要遍历集合元素时都会获取一个新的迭代器。

我们可以使用迭代器模式来遍历组合模式。也可以使用工厂方法模式和迭代器来让子类返回不同的迭代器,并使得迭代器与集合相匹配。

身传递给迭代器的构造函数来创建两者之间的链接。
5. 检查客户端代码, 使用迭代器替代所有集合遍历代码。 每当客户端需要遍历集合元素时都会获取一个新的迭代器。

我们可以使用迭代器模式来遍历组合模式。也可以使用工厂方法模式和迭代器来让子类返回不同的迭代器,并使得迭代器与集合相匹配。


http://www.ppmy.cn/news/1549405.html

相关文章

【C++】undefined reference to `xxx_function’”的错误

1. undefined reference to xxx_function’”的错误时 既然编译是说没有定义某个函数&#xff0c;所以我们先看看这个函数是哪一个库实现的。直接搜索编译环境的include目录&#xff0c;看看 xxx_function 这个函数是定义到哪一个头文件&#xff0c;再看看这个函数是哪个源文件…

DimensionX:单图生成任意的3d/4d视图

DimensionX:单图生成任意的3d/4d视图 通俗易懂的来说 在我们的方法中&#xff0c;关键是如何从一张图片生成动态的3D和4D场景。我们使用一个叫做ST-Director的工具&#xff0c;它可以分开处理空间&#xff08;3D&#xff09;和时间&#xff08;4D&#xff09;两个方面。想象一…

Elasticsearch面试内容整理-分析与映射

在 Elasticsearch 中,分析(Analysis)和映射(Mapping)是数据处理和存储的核心部分。它们共同决定了数据如何被解析、存储以及如何被有效地搜索和查询。以下是关于分析和映射的详细介绍。 分析(Analysis) 分析是将文本数据转换为可以被 Elasticsearch 搜索的索引格式的过程…

爬虫开发工具与环境搭建——使用Postman和浏览器开发者工具

第三节&#xff1a;使用Postman和浏览器开发者工具 在网络爬虫开发过程中&#xff0c;我们经常需要对HTTP请求进行测试、分析和调试。Postman和浏览器开发者工具&#xff08;特别是Network面板和Console面板&#xff09;是两种最常用的工具&#xff0c;能够帮助开发者有效地捕…

玛哈特矫平机:精密制造中的平整大师

在科技飞速发展的今天&#xff0c;精密仪器的制造对材料平整度的要求越来越高&#xff0c;宛如针尖上跳舞。在这一背景下&#xff0c;矫平机作为一种看似简单却至关重要的设备&#xff0c;为精密仪器制造提供了坚实的新支撑。 矫平机的工作原理基于材料的弹性塑性变形特性。它…

Ubuntu ESP32开发环境搭建

文章目录 ESP32开发环境搭建安装ESP-IDF搭建一个最小工程现象 ESP32开发环境搭建 最近有个小项目需要用到能够联网的mcu驱动&#xff0c;准备玩玩esp的芯片&#xff0c;记录下ESP32开发环境搭建的过程。 ESP-IDF 是乐鑫科技为其 ESP32 系列芯片提供的官方开发框架。这个框架主…

Django如何配置多个环境的MySQL数据库

在 Django 项目中配置多个环境的 MySQL 数据库是一个常见的需求&#xff0c;特别是在开发、测试和生产环境中使用不同的数据库配置。你可以通过在 settings.py 文件中使用条件语句或环境变量来实现这一点。 1. 使用环境变量 使用环境变量是一种灵活且安全的方式来配置多个环境…

【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作

1.实验目的 熟悉了解掌握SQL Server软件的基本操作与使用方法&#xff0c;以及通过理论课学习与实验参考书的帮助&#xff0c;熟练掌握使用T-SQL语句和交互式方法对数据表进行插入数据、修改数据、删除数据等等的操作&#xff1b;作为后续实验的基础&#xff0c;根据实验要求重…