设计模式 18 迭代器模式 Iterator Pattern


设计模式 18 迭代器模式 Iterator Pattern
1.定义

迭代器模式 (Iterator Pattern) 是一种行为型设计模式,它提供了一种访问集合元素的标准方法,而无需暴露集合的内部表示。

提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

核心思想来自将遍历集合的逻辑从集合本身中分离出来,封装到一个独立的迭代器对象中。
迭代器对象负责维护遍历的当前位置,并提供访问下一个元素的方法。

想象一个书架,上面摆满了书籍。如果你想阅读这些书籍,你可以选择不同的方式:

  • 直接访问: 你直接走到书架前,从最左边开始一本一本地拿书阅读。
  • 使用书签: 你用书签标记当前阅读的位置,下次阅读时直接从书签处开始。
2.内涵

迭代器模式就像使用书签一样,它提供了一种间接访问集合元素的方式:

迭代器对象: 就像书签,它记录了当前访问的位置。

  • next() 方法: 就像翻到下一页,它返回下一个元素。
  • hasNext() 方法: 就像判断是否有下一页,它判断是否还有下一个元素。
3.案例分析
/Iterator Design Pattern/include <iostream>
include <string>
include <vector>template <typename T, typename U>
class Iterator {public:typedef typename std::vector<T>::iterator iter_type;Iterator(U p_data, bool reverse = false) : m_p_data_(p_data) {m_it_ = m_p_data_->m_data_.begin();}void First() {m_it_ = m_p_data_->m_data_.begin();}void Next() {m_it_++;}bool IsDone() {return (m_it_ == m_p_data_->m_data_.end());}iter_type Current() {return m_it_;}private:U m_p_data_;iter_type m_it_;
};template <class T>
class Container {friend class Iterator<T, Container>;public:void Add(T a) {m_data_.push_back(a);}Iterator<T, Container> CreateIterator() {return new Iterator<T, Container>(this);}private:std::vector<T> m_data_;
};class Data {public:Data(int a = 0) : m_data_(a) {}void set_data(int a) {m_data_ = a;}int data() {return m_data_;}private:int m_data_;
};void ClientCode() {std::cout << "________________Iterator with int______________________________________" << std::endl;Container<int> cont;for (int i = 0; i < 10; i++) {cont.Add(i);}Iterator<int, Container<int>> it = cont.CreateIterator();for (it->First(); !it->IsDone(); it->Next()) {std::cout << it->Current() << std::endl;}Container<Data> cont2;Data a(100), b(1000), c(10000);cont2.Add(a);cont2.Add(b);cont2.Add(c);std::cout << "________________Iterator with custom Class______________________________" << std::endl;Iterator<Data, Container<Data>> it2 = cont2.CreateIterator();for (it2->First(); !it2->IsDone(); it2->Next()) {std::cout << it2->Current()->data() << std::endl;}delete it;delete it2;
}int main() {ClientCode();return 0;
}

上述代码 uml 类图如下


4.注意事项


     迭代器模式 Iterator Pattern 使用时需要注意什么?

    使用迭代器模式时,需要注意以下几点:

    1. 迭代器状态的维护:

     迭代器对象需要维护当前遍历的位置,确保每次调用 `next()` 方法都能返回下一个元素。
     迭代器对象需要处理遍历结束的情况,例如在 `hasNext()` 方法中返回 `false`,或在 `next()` 方法中抛出异常。

    2. 迭代器的类型:

     迭代器可以是内部迭代器,也称为迭代器方法,它将遍历逻辑封装在集合类内部,例如 Java 中的 `forEach` 方法。
     迭代器可以是外部迭代器,它是一个独立的类,负责遍历集合,例如 Java 中的 `Iterator` 接口。

    3. 迭代器的可复用性:

     迭代器对象通常是不可复用的,因为它们维护了遍历状态。
     如果需要多次遍历同一个集合,需要创建新的迭代器对象。

    4. 迭代器的并发访问:

     如果多个线程同时访问同一个迭代器对象,可能会导致数据不一致或异常。
     在并发环境中使用迭代器时,需要进行同步处理,例如使用锁机制来保护迭代器对象。

    5. 迭代器的性能:

     迭代器的性能取决于集合的类型和迭代器的实现方式。
     对于一些集合类型,例如链表,迭代器可能比直接访问元素效率低。

    6. 迭代器的灵活性:

     迭代器模式可以提供灵活的遍历方式,例如正序、逆序、随机访问等。
     可以根据需要自定义迭代器,实现不同的遍历逻辑。

    总结:

    迭代器模式是一种强大的设计模式,它可以简化对集合的遍历操作,并提供灵活的遍历方式。在使用迭代器模式时,需要关注迭代器状态的维护、类型、可复用性、并发访问和性能等方面,以确保代码的正确性和效率。

5.最佳实践


在使用迭代器模式时,除了前面提到的需要注意的地方,还需要遵循以下经验:

1. 明确迭代器职责

迭代器应该只负责遍历集合,不应该包含其他操作,例如修改集合元素。
如果需要修改集合元素,应该使用专门的方法,而不是通过迭代器来实现。


2. 保持迭代器简单

迭代器应该尽可能简单易懂,避免过度设计。
迭代器应该只包含必要的操作,例如 hasNext()、next() 等。


3. 考虑迭代器的性能

如果需要频繁遍历集合,应该选择性能较高的迭代器实现。
对于一些特殊类型的集合,例如链表,可能需要使用自定义迭代器来提高性能。


4. 避免迭代器中的副作用

迭代器不应该修改集合的状态,例如添加或删除元素。
如果需要修改集合,应该使用专门的方法,而不是通过迭代器来实现。


5. 使用迭代器模式的最佳实践

优先使用语言提供的内置迭代器,例如 Java 中的 Iterator 接口。
如果需要自定义迭代器,应该遵循迭代器模式的规范,并提供必要的操作。
避免在迭代器中使用 break 或 continue 语句,因为它们会破坏迭代器的正常逻辑。


6. 迭代器与并发

在并发环境中使用迭代器时,需要格外小心,因为多个线程可能会同时访问同一个迭代器对象。
如果需要在并发环境中使用迭代器,应该使用线程安全的迭代器实现,例如 Java 中的 ConcurrentIterator 接口。

6.总结

        迭代器模式是一种非常实用的设计模式,它可以帮助我们简化对集合的遍历操作,并提高代码的可读性和可维护性。在使用迭代器模式时,遵循以上经验可以帮助我们写出更加健壮和高效的代码。

7.行为模式汇总图

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

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

相关文章

Redis之内存管理过期、淘汰机制

1.Redis内存管理 我们的redis是一个内存型数据库&#xff0c;我们的数据也都是放在内存中的&#xff0c;内存是有限的空间&#xff0c;当数据满了之后&#xff0c;我们要怎么样继续保证redis的可用性呢?我们就需要采取点管理措施和机制来保证我们redis的可用性。 在redis.co…

一套saas模式云MES系统源码,基于springboot+vue.js+uniapp开发

一套saas模式云MES系统源码&#xff0c;基于springbootvue.jsuniapp开发 MES系统简介 MES系统&#xff0c;即制造执行系统&#xff08;Manufacturing Execution System&#xff09;&#xff0c;是一种面向制造企业车间执行层的生产信息化管理系统。它位于上层的企业资源规划&a…

应用案例|精密制造中使用复合机器人得到显著提升

精密制造行业对设备的精度、稳定性和效率要求极高&#xff0c;而复合机器人凭借其多功能性、高度灵活性和精准控制能力&#xff0c;正逐渐成为该领域的新宠。以下是一个富唯智能复合机器人在精密制造中的应用案例。 案例背景 某知名汽车零部件制造企业&#xff0c;专注于生产…

【JS】并发控制

需求 控制网络请求并发数控制并发按顺序返回结果 码 /** * 控制并发 * param {Function} fn 逻辑处理函数 * param {Array} arr 发送的数据 * param {Number} [max3] 并发数 默认3 * param {Number} [orderfalse] 按顺序返回执行结果 默认false * param {Number} [retry1] 重试…

vue项目集成萤石云在Web系统中实现实时摄像头监控及控制功能

需求 需求&#xff1a; 开发人员在产线上放置一个萤石摄像头&#xff0c;前端在可视化大屏上实时监控&#xff0c;且控制左右上下功能。 效果 萤石云接入web前期准备工作 阅读萤石云API文档&#xff1a;萤石云开放平台开发者文档 阅读萤石云控制API文档&#xff1a;萤石云摄…

【错题集-编程题】dd 爱旋转(模拟)

牛客对应题目链接&#xff1a;dd爱旋转 (nowcoder.com) 一、分析题目 模拟题&#xff0c;但是需要不能直接无脑模拟&#xff0c;要思考⼀下规律。 顺时针旋转 180&#xff1a;行变换 列变换行变换、列变换的顺序颠倒不会有影响行变换的次数是个数相当于不变 二、代码 #includ…

《C语言深度解剖》(15):动态内存管理和柔性数组

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多C语言深度解剖点击专栏链接查看&…

k8s中的集群调度

文章目录 k8s中的集群调度Pod 创建流程 通过指定节点来创建pod所在的node节点通过标签来指定pod创建在哪个节点上pod 的亲和性Pod的亲和性和反亲和性亲和性&#xff08;Affinity&#xff09;反亲和性&#xff08;Anti-Affinity&#xff09; 污点与容忍污点&#xff08;Taint&am…

Spring Cache入门详解

一、概述 1.1缓存介绍 Spring提供了一套cache缓存抽象(注解/接口)&#xff0c;使基于spring缓存的使用与实现解耦 默认实现&#xff0c;Spring JDK ConcurrentMap-based Cache第三方实现&#xff0c;caffeine/Ehcache/Redis等 https://docs.spring.io/spring-framework/do…

Postman快捷功能-快速填写请求头

大家好&#xff0c;之前给大家分享关于 Postman 工具的基础使用&#xff0c;今天给大家介绍一个快捷功能&#xff0c;可以一定程度提高我们使用 Postman 工具的效率&#xff0c;在我们进行接口测试时&#xff0c;几乎每个接口都需要填写 Headers&#xff0c;且 Headers 中的参数…

【ai】livekit服务本地开发模式2:模拟1个发布者

是一个会议用软件:LiveKit is an open source project that provides scalable, multi-user conferencing based on WebRTC. It’s designed to provide everything you need to build real-time video audio data capabilities in your applications.LiveKit’s server is wr…

【Python】 Django 框架如何支持百万级日访问量

基本原理 Django 是一个高级的 Python Web 框架&#xff0c;它鼓励快速开发和干净、实用的设计。Django 遵循 MVC&#xff08;模型-视图-控制器&#xff09;设计模式&#xff0c;允许开发者通过编写更少的代码来构建高质量的 Web 应用程序。Django 自带了许多内置功能&#xf…

发现没:随便搞个B端页面,就想在客户那里过关,难啦。

客户对B端界面要求越来越高的原因可以有以下几点&#xff1a; 用户体验要求提升&#xff1a;随着用户对移动应用和网页的使用经验增加&#xff0c;他们对于界面的交互、流畅性和易用性要求也越来越高。他们希望能够在使用B端应用时&#xff0c;能够快速、方便地完成任务&#…

设计模式详解(六):适配器模式——Adapter

目录导航 适配器模式及其作用现实生活举例 适配器模式的好处适配器模式的实现关系图实现步骤 适配器模式的适用场景适配器模式示例 适配器模式及其作用 适配器模式是一种结构型设计模式。所谓结构型是指在代码结构方面的设计模式。适配器模式作为中间层&#xff0c;可以让交互…

Vue3 图片或视频下载跨域或文件损坏的解决方法

Vue3 图片或视频下载跨域或文件损坏的解决方法 修改跨域配置文件下载方法 修改跨域配置文件 修改vite.config.ts文件proxy里面写跨域地址&#xff0c;如下图&#xff0c;图片地址就是我们要跨域的目标地址&#xff1a; 下载方法 如下就是我取消上面那句后的报错 然后调用两…

【Java】Sping Boot中使用Javax Bean Validation

目录 Javax Bean Validation在Spring Boot中集成Javax Bean Validation使用案例功能测试配置全局异常处理器重新测试返回特定形式的信息方式一方式二 附&#xff1a;常用的注解 Javax Bean Validation Javax Bean Validation是Java平台的一项规范&#xff0c;旨在提供一种简单…

想知道股指期货和期权有什么不同吗?

市场上目前有中金所的沪深300ETF&#xff0c;中证500和中证1000股指期货&#xff0c;期权市场有上证50ETF&#xff0c;沪深300etf和中证500ETF期权&#xff0c;股指期货和期权在买卖双方的权利义务、风险收益特征、保证金制度、上市合约数量等方面均有较大区别&#xff0c;下文…

每天学点小知识:Windows终端Powershell美化

前言 本章的旨在教会你美化自己的终端&#xff0c;powershell需要以管理员运行 经过我的测试&#xff0c;不同的电脑可能会有不同的报错&#xff0c;具体操作根据官方为主https://ohmyposh.dev/docs 效果展示 Oh My Posh&#xff1a;提供美观的 PowerShell 提示符主题 1.安装…

揭秘CISA:你不知道的信息安全认证,轻松掌握职场先机!

在当今的信息化时代&#xff0c;信息系统的安全和稳定是企业和组织的重要资产。信息系统审计是一项专业的工作&#xff0c;需要具备丰富的知识和经验&#xff0c;以及敏锐的洞察力和判断力。信息系统审计师是信息系统审计领域的专业人士&#xff0c;他们负责对信息系统的设计、…

【OpenGL实践12】关于缓存区Framebuffer的运用

文章目录 一、说明二、帧缓冲区三、创建新的帧缓冲区四、附属装饰4.1 纹理图像4.2 渲染缓冲区对象图像 五、使用帧缓冲区5.1 后期处理5.2 更改代码 六、后期处理效果6.1 色彩处理6.2 模糊6.3 Sobel算子 七、结论练习 一、说明 关于FrameBuffer的使用&#xff0c;是OpenGL的高级…