设计模式 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.rhkb.cn/news/332706.html

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

相关文章

B树与B+树区别

B树和B树是常见的数据库索引结构&#xff0c;都具有相较于二叉树层级较少&#xff0c;查找效率高的特点&#xff0c;它们之间有以下几个主要区别&#xff1a; 1.节点存储数据的方式不同 B树的叶子结点和非叶子节点都会存储数据&#xff0c;指针和数据共同保存在同一节点中B树…

vue 引入 emoji 表情包

vue 引入 emoji 表情包 一、安装二、组件内使用 一、安装 npm install --save emoji-mart-vue二、组件内使用 import { Picker } from "emoji-mart-vue"; //引入组件<picker :include"[people,Smileys]" :showSearch"false" :showPreview&q…

YAML详情

一、kubernetes支持对象 Kubernetes支持YAML和JSON格式管理资源对象 JSON格式&#xff1a;主要用于api接口之间消息的传递YAML格式&#xff1a;用于配置和管理&#xff0c;YAML是一种简洁的非标记性语言&#xff0c;内容格式人性化&#xff0c;较易读 二、YAML语法格式注意点 …

微信小程序开发 tabbar组件常见问题

一、 tabbar不显示问题 问题 刚开始我在app.json中配置了下面的代码&#xff0c;但tabbar并没有显示。代码如下&#xff1a; "tabBar": {"custom": true,"color": "#7A7E83","selectedColor": "#3cc51f","…

C++ | Leetcode C++题解之第113题路径总和II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> ret;unordered_map<TreeNode*, TreeNode*> parent;void getPath(TreeNode* node) {vector<int> tmp;while (node ! nullptr) {tmp.emplace_back(node->val);node …

单点登录与JWT

JWT:JSON Web Token JWT的作用是用户授权&#xff08;Authorization&#xff09;,而不是用户的身份认证&#xff08;Authentication&#xff09; 授权&#xff08;Authorization&#xff09;vs认证&#xff08;Authentication&#xff09; 用户认证指的是使用用户名、密码来…

pytest:指定测试用例执行顺序

在自动化测试中&#xff0c;测试用例的执行顺序有时对测试结果具有重要影响。本文将介绍如何在pytest框架中使用pytest-ordering插件以及Collection hooks来控制测试用例的执行顺序。 方式1&#xff1a; 使用pytest-ordering插件控制执行顺序 1.1 安装pytest-ordering插件 首…

XShell-连接-Centos 7

XShell 连接Centos 7 一.准备 安装XShell XShell下载地址&#xff1a; 在虚拟机上安装Centos 7&#xff0c;具体操作自行学习 二.Centos 7的准备 1.网络适配器修改为NAT 2.获取IP 输入命令&#xff1a; ip addr我的Centos 7对外IP为192.168.174.129 三.XShell连接Cento…

设计模式:适配器模式(Adapter)

设计模式&#xff1a;适配器模式&#xff08;Adapter&#xff09; 设计模式&#xff1a;适配器模式&#xff08;Adapter&#xff09;模式动机模式定义模式结构时序图模式实现在单线程环境下的测试在多线程环境下的测试模式分析优缺点适用场景应用场景应用实例适配器模式和代理模…

新书推荐:7.1 do while语句

本节必须掌握的知识点&#xff1a; 示例二十二 代码分析 汇编解析 ■do while语句其语法形式&#xff1a; do{ 语句块; }while(表达式) ■语法解析&#xff1a; ●执行do循环体内的语句块&#xff1b; ●判断while语句里的表达式&#xff0c;表达式为真继续下次循环&#…

上位机图像处理和嵌入式模块部署(f103 mcu运行freertos)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 mcu一般有两个用途,一个是控制,一个是非控制。控制类的应用一般要求实时性比较高,什么时候做什么,都是有严格的时间要求的。而非控制类的应用,则要求实现尽可能多的功能,比如…

PanTools v1.0.25 多网盘批量管理工具 批量管理、分享、转存、重命名、复制...

一款针对多个热门网盘的文件管理、批量分享、批量转存、批量复制、批量重命名、批量链接检测、跨账号移动文件、多账号文件搜索等&#xff0c;支持不同网盘的不同账号的资源文件操作。适用于网站站长、资源爱好者等&#xff0c;对于管理名下具有多个网盘多个账号具有实用的效果…

2024.05.26 第 399 场周赛

Leetcode 第 399 场周赛 优质数对的总数 I Leetcode 优质数对的总数 I 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#xff08;0 < i < n…

React自定义Componment和State深层次理解-07

本节主要从底层原理上分析下React开发相关的内容和注意事项&#xff0c;本节会围绕使用展开&#xff0c;而非源码讲解。 Componment详解 什么是组件 在 MVVM架构出现之前&#xff0c;组件主要分为两种。 狭义上的组件&#xff0c;又称为 UI 组件&#xff0c;比如 Tabs 组件、…

PC端应用订阅SDK接入攻略

本文档介绍了联想应用联运sdk接入操作指南&#xff0c;您可在了解文档内容后&#xff0c;自行接入应用联运sdk。 1. 接入前准备 1. 请先与联想商务达成合作意向。 2. 联系联想运营&#xff0c;提供应用和公司信息&#xff0c;并获取商户id、app id、key&#xff08;公私钥、…

Linux定时计划

定时计划 一、计划任务种类 突发性&#xff1a;临时决定只执行一次的任务 at&#xff1a;处理执行一次任务就结束定时性&#xff1a;每隔一定时间需要重复执行此命令 crontab&#xff1a;指定任务&#xff0c;按照设定的周期一直循环执行二、作用 定时任务可以用于自动备份…

如何将Windows PC变成Wi-Fi热点?这里提供详细步骤

序言 Windows 10和Windows 11都有内置功能,可以将你的笔记本电脑(或台式机)变成无线热点,允许其他设备连接到它并共享你的互联网连接。以下是操作指南。 由于Windows中隐藏的虚拟Wi-Fi适配器功能,你甚至可以在连接到另一个Wi-Fi网络或无线路由器时创建Wi-Fi热点,通过另…

Navicat 连接 OceanBase 快速入门 | 社区版

Navicat Premium&#xff08;16.1.9或更高版本&#xff09;正式支持 OceanBase全线数据库产品。OceanBase为现代数据架构打造的开源分布式数据库。兼容 MySQL 的单机分布式一体化国产开源数据库&#xff0c;具有原生分布式架构&#xff0c;支持金融级高可用、透明水平扩展、分布…

分布式音乐播放器适配了Stage模型

OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;应用开发自API 8及其更早版本一直使用的是FA模型进行开发。FA模型是Feature Ability的缩写&#xff0c;它和PA&#xff08;Particle Ability&#xff09;两种类型是过往长期推广的术语&#xff0c;深入人心…

95.网络游戏逆向分析与漏洞攻防-ui界面的设计-ui的设计与架构

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…