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

迭代器模式

    • C++ 设计模式——迭代器模式
      • 1. 主要组成成分
      • 2. 迭代器模式范例
        • 2.1 抽象迭代器
        • 2.2 抽象容器
        • 2.3 具体的迭代器
        • 2.4 具体的容器
        • 2.5 主函数示例
      • 3. 迭代器 UML 图
          • 3.1 迭代器 UML 图解析
      • 4. 迭代器模式的优点
      • 5. 迭代器模式的缺点
      • 6. 迭代器模式的适用场景
      • 7. 现代C++中的迭代器
      • 总结

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

迭代器模式是一种行为设计模式,旨在提供一种方法来顺序访问集合对象中的元素,而不暴露集合的内部结构。

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

1. 主要组成成分

  1. 迭代器接口 (Iterator):定义访问和遍历元素的基本方法,如 next(), hasNext(), currentItem() 等。
  2. 具体迭代器 (Concrete Iterator):实现迭代器接口,维护对集合的引用,并跟踪当前遍历的位置。
  3. 聚合接口 (Aggregate):定义创建迭代器的接口,通常包含一个方法如 createIterator()
  4. 具体聚合 (Concrete Aggregate):实现聚合接口,包含集合的具体数据结构(如数组、链表等),并实现创建迭代器的方法。

2. 迭代器模式范例

以下是一个简单的迭代器模式实现范例,使用一个固定大小的数组作为容器。

2.1 抽象迭代器

在抽象迭代器模板中实现了四个基本方法,这些方法通常被视为迭代器接口的最小要求。

//抽象迭代器类模板
template <typename T>
class myIter
{
public:virtual void First() = 0;     //指向容器中第一个元素virtual void Next() = 0;      //指向下一个元素virtual bool IsDone() = 0;    //是否遍历完virtual T& CurrentItem() = 0; //获取当前的元素virtual ~myIter() {}          //做父类时析构函数应该为虚函数
};
2.2 抽象容器

在抽象容器类模板中定义了一个 CreateIterator 接口,后续在具体的容器子类中,会运用工厂模式创建相应的迭代器。

//抽象容器类模板
template <typename T>
class myCotainer
{
public:virtual myIter<T>* CreateIterator() = 0; //创建迭代器virtual T& getItem(int index) = 0; //获取当前元素virtual int getSize() = 0;  //容器中元素数量virtual ~myCotainer() {}  //做父类时析构函数应该为虚函数
};
2.3 具体的迭代器

具体迭代器(myVectorIter)实现了抽象迭代器接口,并提供对具体容器(myVector)的访问和遍历功能。

//具体迭代器类模板,为简单起见,本迭代器针对的是大小为10个元素的数组
template <typename T>
class myVectorIter :public myIter<T>
{
public:myVectorIter(myCotainer<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:myCotainer<T>* myvector;int m_current;  //记录数组的当前下标(迭代器在当前容器中的位置)
};
2.4 具体的容器

具体容器(myVector)实现了抽象容器接口,负责存储数据、管理元素,并提供创建迭代器的功能。

//具体容器类模板
template <typename T>
class myVector :public myCotainer<T>
{
public:myVector(){//将数组中元素进行初始化for (int i = 0; i < 10; ++i){m_elem[i] = i;}}virtual myIter<T>* CreateIterator(){//工厂模式,注意实参传递进去的是该容器的指针thisreturn new myVectorIter<T>(this); //要考虑在哪里释放的问题}virtual T& getItem(int index){return m_elem[index];}virtual int getSize(){return 10; //为简化代码,返回固定数字}
private://为了简化代码,将容器实现为固定装入10个元素的数组T m_elem[10];
};
2.5 主函数示例

以下是两个不同实现的 main 函数,展示了如何使用迭代器。

使用具体迭代器(非多态机制):直接使用具体迭代器,性能更优,适合简单的遍历场景,因为它避免了多态引入的额外开销。

int main() 
{myCotainer<int>* pcontainer = new myVector<int>();myVectorIter<int> iter(pcontainer);//遍历容器中的元素for (iter.First(); !iter.IsDone(); iter.Next()) //非多态机制,可以明显改善程序性能{cout << iter.CurrentItem() << endl;}//释放资源delete pcontainer;return 0;
}

使用抽象迭代器(多态机制):使用抽象迭代器,提供了更大的灵活性和扩展性,但性能较低,适合需要不同迭代策略的复杂场景。下面代码中的for循环所调用的迭代器接口 FirstIsDoneNextCurrentItem 都是多态机制。显然,如果容器中的元素数量非常庞大,则会非常影响程序的运行效率。因此,如果不是必须使用迭代器的多态机制,可以将迭代器的内存在栈中分配,这对改善程序运行性能将起到很好的作用。

int main() 
{myCotainer<int>* pcontainer = new myVector<int>();myIter<int>* iter = pcontainer->CreateIterator();//遍历容器中的元素for (iter->First(); !iter->IsDone(); iter->Next()) //多态机制的遍历,效率上不好,尽量考虑栈机制{cout << iter->CurrentItem() << endl;}//释放资源delete iter;delete pcontainer;
}

无论使用哪种方式,输出结果都是:

0
1
2
3
4
5
6
7
8
9

3. 迭代器 UML 图

迭代器模式 UML 图

3.1 迭代器 UML 图解析
  • Iterator (抽象迭代器):用于定义访问和遍历容器中元素的接口。这部分对应 myIter 类模板。
  • ConcreteIterator (具体迭代器):实现了抽象迭代器的接口,完成对聚合对象(容器)中元素的遍历,记录当前元素的位置。这部分对应 myVectorIter 类模板。
  • Aggregate (抽象聚合):将聚合理解成容器,声明一个 CreateIterator 方法用于创建一个迭代器对象,充当创建迭代器的工厂角色。这部分对应 myContainer 类模板。
  • ConcreteAggregate (具体聚合):实现了抽象聚合的 CreateIterator 方法以创建相应的迭代器,该方法返回具体迭代器的一个适当实例。这部分对应 myVector 类模板。

4. 迭代器模式的优点

  • 单一职责原则:迭代器模式将集合对象的遍历行为从集合对象本身分离出来,由迭代器负责,这样使得集合对象和迭代器各自承担单一的职责,降低它们之间的耦合。
  • 开闭原则:迭代器模式支持以不同的方式遍历一个聚合对象,在不改变聚合对象结构的前提下,可以定义新的迭代器类来支持新的遍历方式。
  • 可扩展性:可以根据需要,增加新的迭代器类来扩展系统的功能,如实现反向迭代器或过滤迭代器等。
  • 封装性:迭代器模式封装了遍历算法的细节,用户不需要知道集合对象的内部结构即可进行遍历。

5. 迭代器模式的缺点

  • 类爆炸:为了支持多种遍历方式,可能需要定义很多具体的迭代器类,增加了系统的复杂性。
  • 性能开销:使用迭代器模式可能比直接遍历集合对象要慢,因为需要通过接口进行函数调用,而不是直接访问数据。

6. 迭代器模式的适用场景

  • 访问聚合对象的内容而不暴露其内部表示:迭代器模式允许客户端通过迭代器对象访问聚合对象的元素,而不需要了解聚合对象的具体实现。这种封装提高了代码的灵活性和可维护性。
  • 支持多种不同的遍历方式:在某些情况下,可能需要以不同的顺序或策略遍历同一个集合(例如前序遍历、后序遍历等)。迭代器模式可以轻松实现这些不同的遍历方式,而不需要修改聚合对象的内部结构。
  • 提供统一的接口来遍历不同的聚合结构:迭代器模式为不同类型的聚合对象提供了一个共同的接口,使得客户端可以使用相同的方式遍历不同的集合。这种一致性简化了代码的使用,增强了可扩展性。
  • 需要支持并发遍历:在复杂系统中,可能需要多个线程同时遍历同一个集合。迭代器模式可以设计为支持并发访问,确保线程安全。
  • 需要在不暴露集合实现的情况下实现复杂的遍历逻辑:当遍历逻辑变得复杂时(例如,过滤、映射等),可以使用迭代器将这些逻辑与集合的实现分离,使代码更清晰。
  • 需要延迟加载或惰性求值:迭代器模式可以实现惰性求值,只有在需要时才加载元素,从而节省内存和计算资源。

7. 现代C++中的迭代器

在C++标准库中,迭代器模式被广泛应用。C++标准库中的容器(如 std::vector, std::list, std::map 等)都提供了迭代器来访问容器中的元素。以下是C++中迭代器的一些特点:

  • 标准迭代器:C++标准库定义了五种迭代器类别,包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。
  • 迭代器适配器:C++还提供了迭代器适配器,如 std::reverse_iterator 用于反向遍历容器,std::istream_iteratorstd::ostream_iterator 用于流操作。
  • 泛型编程:迭代器与模板结合使用,可以实现泛型算法,如 std::sortstd::find 等算法可以用于任何提供相应迭代器接口的容器。
  • 智能指针:C++中的智能指针(如 std::unique_ptr, std::shared_ptr)虽然不是传统意义上的迭代器,但它们提供了对动态分配内存的管理和访问,类似于迭代器的功能。

总结

迭代器模式通过提供一种统一的接口来访问不同类型的集合,增强了代码的可读性和可维护性。尽管存在一些缺点,如类的增加和性能开销,但其优点使得在需要灵活访问集合的场景中非常有效。理解和应用迭代器模式对于提高编程能力和设计模式的掌握至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408551.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习】使用Conda虚拟环境安装多个版本的CUDA和CUDNN方便切换

conda虚拟环境安装CUDA和CUDNN 官网教程 https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#conda-installation 1. 背景 深度学习用显卡训练的时候&#xff0c;需要安装与显卡对应的cuda和cudnn。但不同的项目所支持的pytorch版本是不一样的&#x…

Openssl Infinite Loop 漏洞(CVE-2022-0778)

Openssl Infinite Loop 漏洞&#xff08;CVE-2022-0778&#xff09; 1. 漏洞详情 在该漏洞中由于证书解析时使用的 BN_mod_sqrt() 函数存在一个错误&#xff0c;它会导致在非质数的情况下永远循环。可通过生成包含无效的显式曲线参数的证书来触发无限循环。由于证书解析是在验…

视频监控汇聚算法平台训练站车辆类型算法分析车辆类型检测应用方案

车辆类型检测算法是计算机视觉和深度学习技术在交通管理和智能车辆系统中的重要应用之一。这种算法通过自动分析和识别车辆图像&#xff0c;能够准确判断车辆的类型&#xff0c;如轿车、SUV、货车等。 运用方案 数据采集与预处理 采集包含车辆的图像或视频数据&#xff0c;包…

自学成才

软件只是一种工具&#xff0c;正如给你一张纸和一支笔&#xff0c;有人满纸疙瘩&#xff0c;有人行云流水唱成一曲绝唱&#xff0c;全在于笔头功夫。使用软件一样需要智慧&#xff0c;不光是懂了就行&#xff0c;还得创造性使用&#xff0c;才会成就别人望洋兴叹的绝活。 Core…

【实施】软件实施方案(word套用)

软件实施方案 二、 项目介绍 三、 项目实施 四、 项目实施计划 五、 人员培训 六、 项目验收 七、 售后服务 八、 项目保障措施 软件开发全套资料获取&#xff1a;&#xff08;本文末个人名片也可直接获取&#xff09; 软件产品&#xff0c;特别是行业解决方案软件产品不同于一…

【Electron】桌面应用开发electron-builder打包报错问题处理

Electron 桌面应用开发electron-builder打包过程中各种报错问题处理 前一篇有写过 Electron 桌面应用开发快速入门到打包Windows应用程序 在安装到打包的整个过程中&#xff0c;我们都会遇到很多诡异的问题&#xff0c;接下来我将介绍我遇到的几个问题的解决方案 一、拉包的时…

VBA技术资料MF191:将源文件夹所有文件移动到目标文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

iOS profiles文件过期如何更新

创建发布用的Certificates 首先进入到https://developer.apple.com/account页面选择【证书】进入【新建证书】页面 点击【新建证书】按钮&#xff1a; 根据需求选中对应的【证书类型】&#xff0c;我选的是【Apple Distribution】&#xff0c; 开发者证书选择【Apple Devel…

react antd TreeSelect实现自定义标签

<ProFormTreeSelectlabel"接收对象"name"receiverObjects"colProps{{ span: 16 }}labelCol{{span: 6,}}wrapperCol{{span: 18,}}rules{[{ required: true }]}fieldProps{{showSearch: true,multiple: true,// autoClearSearchValue: true,filterTreeNod…

探索条形码与二维码的秘密:pyzbar库的神奇之旅

文章目录 探索条形码与二维码的秘密&#xff1a;pyzbar库的神奇之旅背景&#xff1a;为什么选择pyzbar&#xff1f;pyzbar是什么&#xff1f;如何安装pyzbar&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索条形码与二维码的秘密&#xff1a;pyzbar库的神奇之…

数字化与进制转换

1.数字化是什么&#xff1f; 数字化是将事物的属性转化为计算机可处理对象的过程。 2.数字化的好处&#xff1f; 可以让我们的生活&#xff0c;学习和工作更加便捷&#xff0c;大大提升我们学习和工作的效率。 3.如何将采集到的数据进行数字化&#xff1f; 可以通过两种信…

爬取央视热榜并存储到MongoDB

1. 环境准备 在开始之前&#xff0c;确保你已经安装了以下Python库&#xff1a; pip install requests pymongo2. 爬取网页内容 首先&#xff0c;我们需要爬取央视热榜的网页内容。通过requests.get()方法&#xff0c;我们可以获取网页的HTML内容&#xff0c;并通过re.finda…

Linux--gdb的常用命令

目录 前言 一、gdb是什么&#xff1f; 二、常用命令 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 对于程序有两个版本&#xff0c;一个是debug版和release版&#xff0c;要想进行调试必须使用debug版本&#xff0c;再Linux上进行调试就要用到调试器…

实习手记(8):增删改查

上周又偷懒了没有按时写博客&#xff08;扣大分啊啊&#xff01;&#xff09;但是好像也没有人看呢~其实最开始也只是想着记录一下实习历程&#xff0c;怕自己之后回过头想关于实习的都想不起来了&#xff0c;个人还是喜欢记录有关自己的学习生活的&#xff0c;就算没啥人看但回…

Elasticsearch安装 Kibana安装

安装Elasticsearch 一、拉取镜像或者上传 docker pull Elasticsearch 二、将上传的镜像导入(在仓库拉取的这一步跳过) docker load -i es.tar docker load -i 三、创建容器 1.Elasticsearch 注意修改到自己的网络&#xff08;第八行&#xff09; docker run -d \--nam…

ES 支持乐观锁吗?如何实现的?

本篇主要介绍一下Elasticsearch的并发控制和乐观锁的实现原理&#xff0c;列举常见的电商场景&#xff0c;关系型数据库的并发控制、ES的并发控制实践。 并发场景 不论是关系型数据库的应用&#xff0c;还是使用Elasticsearch做搜索加速的场景&#xff0c;只要有数据更新&…

“Docker中部署Kibana:步骤与指南“

博主这篇文章是跟Elasticsearch那篇文章是有关系的&#xff0c;建议大家先去看&#xff1a; 轻松上手&#xff1a;Docker部署Elasticsearch&#xff0c;高效构建搜索引擎环境_docker 启动 es-CSDN博客 这篇博文&#xff0c;还有镜像下载不下来的情况&#xff0c;大家可以去看…

pikachu-ssrf_redis

目录 SSRF 1、SSRF漏洞介绍&#xff1a; 2、SSRF漏洞原理&#xff1a; 3、SSRF漏洞利用手段&#xff1a; 4、SSRF漏洞绕过方法&#xff1a; SSRF(curl)用法 1、通过网址访问链接 2、利用file协议查看本地文件 3、dict协议扫描内网主机开放端口 4.gopher&#xff1a;威…

计算机网络基础 - 应用层(1)

计算机网络基础 应用层网络应用的体系结构C/S 体系结构P2P 体系结构C/S 和 P2P 体系结构的混合体 进程通信概述套接字&#xff08;Socket&#xff09;TCP socketUDP socket 应用层协议应用层需要传输层提供的服务Web 与 HTTP概念非持续连接和持续连接HTTP报文格式请求报文响应报…

vs code中编写html的配置,插件安装

首先安装vs code 插件安装下面三个&#xff1a; 功能分别是&#xff1a; html css support &#xff1a;就是支持html环境&#xff0c;因为vs code就是一个文本编辑器 live server&#xff1a;自动更新编写的文件在浏览器刷新 auto rename tag&#xff1a;自动修改另一半标签…