重温设计模式--迭代器模式

news2025/1/14 10:26:03

文章目录

      • 迭代器模式(Iterator Pattern)概述
      • 迭代器模式的结构
      • 迭代器模式UML图
      • C++ 代码示例
      • 应用场景

迭代器模式(Iterator Pattern)概述

  1. 定义
    迭代器模式是一种行为型设计模式,它提供了一种方法来顺序访问一个聚合对象(如数组、列表、树等各种容器类型的数据结构)中的各个元素,而又无需暴露该聚合对象的内部表示。简单来说,就是将遍历数据结构的操作和数据结构本身分离开来,让遍历的逻辑更加独立和通用。

  2. 作用

    • 解耦数据结构与遍历逻辑:使得数据结构(如容器类)的设计可以专注于存储和管理元素,而不用关心如何遍历这些元素。同时,遍历的逻辑可以独立于具体的数据结构进行修改和扩展,例如,对于不同类型的容器(数组、链表等),可以使用相同的迭代器接口来进行遍历,提高了代码的可维护性和复用性。
    • 支持多种遍历方式:同一个聚合对象可以有多种不同的迭代器实现,以提供不同的遍历顺序或规则。比如对于一个二叉树结构,可以有中序遍历、前序遍历、后序遍历等不同的迭代器,方便根据具体需求来访问数据。
    • 符合开闭原则:当需要对聚合对象添加新的遍历方式或者修改遍历逻辑时,只需要创建新的迭代器类或者修改已有的迭代器类,而不需要改动聚合对象的代码,对扩展开放,对修改关闭。

迭代器模式的结构

  1. 抽象聚合(Aggregate)类
    它是所有聚合对象的抽象,定义了创建迭代器对象的接口,通常会有一个类似createIterator()这样的抽象方法,用于返回对应的迭代器对象,供客户端获取来遍历聚合对象中的元素。

  2. 具体聚合(Concrete Aggregate)类
    实现了抽象聚合类的接口,它内部维护了数据元素的存储结构,并且实现了创建迭代器的方法,返回的是与自身数据结构相匹配的具体迭代器对象,这样客户端就能通过这个迭代器来访问它所包含的元素。

  3. 抽象迭代器(Iterator)类
    定义了遍历聚合对象的接口,通常包含诸如first()(定位到第一个元素)、next()(移动到下一个元素)、isDone()(判断是否遍历完所有元素)、currentItem()(获取当前元素)等抽象方法,这些方法规范了遍历操作的基本行为,所有具体的迭代器都要实现这些方法。

  4. 具体迭代器(Concrete Iterator)类
    实现了抽象迭代器类定义的接口,针对具体的聚合对象的存储结构,实现了具体的遍历逻辑,通过内部指针或索引等方式来跟踪当前遍历的位置,从而正确地实现各个遍历操作方法,使得客户端可以按照期望的方式遍历聚合对象中的元素。

迭代器模式UML图

在这里插入图片描述

C++ 代码示例

以下以一个简单的自定义数组容器为例,来展示迭代器模式的代码实现。

#include <iostream>

// 抽象迭代器类
class Iterator
{
public:
	virtual void first() = 0;
	virtual void next() = 0;
	virtual bool isDone() = 0;
	virtual int currentItem() = 0;
	virtual ~Iterator() {}
};

// 抽象聚合类
class Aggregate
{
public:
	virtual Iterator* createIterator() = 0;
	virtual ~Aggregate() {}
};

// 具体聚合类:自定义数组容器
class MyArray : public Aggregate 
{
private:
	int* elements;
	int size;
public:
	MyArray(int* arr, int s) : elements(arr), size(s) {}
	Iterator* createIterator() override
	{
		return new ArrayIterator(this);
	}
	int getSize()
	{
		return size;
	}
	int at(int index)
	{
		return elements[index];
	}
};

// 具体迭代器类:针对自定义数组的迭代器
class ArrayIterator : public Iterator
{
private:
	MyArray* array;
	int index;
public:
	ArrayIterator(MyArray* arr) : array(arr), index(0) {}
	void first() override
	{
		index = 0;
	}
	void next() override
	{
		index++;
	}
	bool isDone() override
	{
		return index >= array->getSize();
	}
	int currentItem() override
	{
		return array->at(index);
	}
};

int main() 
{
	int arr[] = {1, 2, 3, 4, 5};
	MyArray myArray(arr, 5);
	Iterator* it = myArray.createIterator();
	for (it->first();!it->isDone(); it->next())
	{
		std::cout << it->currentItem() << " ";
	}
	std::cout << std::endl;
	delete it;
	return 0;
}

在上述代码中:

  • Iterator是抽象迭代器类,定义了迭代器的基本操作接口,规范了遍历的通用行为。
  • Aggregate是抽象聚合类,声明了创建迭代器的抽象方法,作为所有聚合对象的抽象基类。
  • MyArray是具体聚合类,它内部持有一个整数数组作为实际存储的数据结构,实现了createIterator方法,返回一个针对自身结构的ArrayIterator对象,以便外部能获取迭代器来遍历数组元素。
  • ArrayIterator是具体迭代器类,它通过维护一个索引变量来跟踪当前遍历的位置,实现了firstnextisDonecurrentItem等方法,按照顺序正确地遍历MyArray中的元素。在main函数中,创建了一个MyArray对象,获取其迭代器并通过循环利用迭代器的方法来遍历数组元素并输出,展示了迭代器模式在自定义数组容器中的简单应用,体现了数据结构与遍历逻辑分离以及通过统一接口进行遍历的特点。

应用场景

  1. 容器类库的实现
    像C++标准模板库(STL)中的各种容器(如vectorlistmap等)都广泛应用了迭代器模式。它们提供了对应的迭代器,使得用户可以方便地遍历容器中的元素,而且不同容器的迭代器遵循统一的接口规范,比如都可以使用begin()end()方法获取迭代器的起始和结束位置,方便了算法函数(如std::for_eachstd::find等)对不同容器元素的操作,提高了代码的通用性和复用性。
  2. 数据库查询结果集遍历
    在数据库编程中,当执行查询语句后会返回一个结果集,这个结果集可以看作是一个聚合对象。使用迭代器模式可以创建相应的迭代器来遍历结果集中的每一条记录(通常包含多个字段的数据),按照一定顺序获取记录中的数据,方便后续的数据处理和展示,而且不同数据库系统的结果集都可以通过实现类似的迭代器接口来提供统一的遍历方式,便于上层应用程序的开发。
  3. 树形结构数据遍历
    对于二叉树、多叉树等树形结构的数据,如文件系统目录树(文件夹可以包含子文件夹和文件,类似树的节点和子节点关系)、组织结构树(部门包含子部门和员工等),可以利用迭代器模式创建不同遍历顺序(如前序、中序、后序遍历二叉树,深度优先或广度优先遍历一般的树形结构)的迭代器,方便按照特定需求访问树中的各个节点元素,进行节点数据的获取、统计等操作。
  4. 游戏地图元素遍历
    在游戏开发中,游戏地图通常由多个地块(如方格、区域等)组成,这些地块可以看作是一个聚合对象。通过迭代器模式,可以创建合适的迭代器来遍历地图上的各个地块,例如查找特定类型的地块(有怪物的地块、有宝藏的地块等)、统计地块数量等,并且如果地图结构发生变化(如增加新区域、改变地块布局等),只需要调整迭代器的实现或者创建新的迭代器,而不需要大规模改动地图本身的管理代码。

由于迭代器模式应用场景太多,而且频次较大,C++ C# Python等语言已经把迭代器模式嵌入到语言中了,不需要用户进行专门的迭代器设计,比如C++ STL list

#include<iostream>
#include<list>
using namespace std;

int main()
{
	list<int> m_list;
	for(int i=0;i<10;++i)
	{
		m_list.push_back(i);
	}

	list<int>::iterator itr = m_list.begin();
	for(;itr!=m_list.end(); ++itr)
	{
		cout<<*itr<<endl;
	}
	return 0;
}

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

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

相关文章

大数据机器学习算法和计算机视觉应用07:机器学习

Machine Learning Goal of Machine LearningLinear ClassificationSolutionNumerical output example: linear regressionStochastic Gradient DescentMatrix Acceleration Goal of Machine Learning 机器学习的目标 假设现在有一组数据 x i , y i {x_i,y_i} xi​,yi​&…

华院计算参与项目再次被《新闻联播》报道

12月17日&#xff0c;央视《新闻联播》播出我国推进乡村振兴取得积极进展。其中&#xff0c;华院计算参与的江西省防止返贫监测帮扶大数据系统被报道&#xff0c;该系统实现了由原来的“人找人”向“数据找人”的转变&#xff0c;有效提升监测帮扶及时性和有效性&#xff0c;守…

【视觉惯性SLAM:相机成像模型】

相机成像模型介绍 相机成像模型是计算机视觉和图像处理中的核心内容&#xff0c;它描述了真实三维世界如何通过相机映射到二维图像平面。相机成像模型通常包括针孔相机的基本成像原理、数学模型&#xff0c;以及在实际应用中如何处理相机的各种畸变现象。 一、针孔相机成像原…

使用RTP 协议 对 H264 封包和解包,h264的avpacket和NAL的关系

学习内容&#xff1a; 本章探讨如何将h264的 avpacket的视频 数据&#xff0c;通过RTP协议发送到 流媒体 服务器 或者 对端接受者。 前提 我们在将 YUV数据变成avframe后&#xff0c;通过h264 编码变成AVPacket&#xff0c;例如&#xff0c;在安防项目中&#xff0c;或者直播…

python 随笔80%核心笔记(一)

目录 一、海龟 二、pygame 三、函数 四、类与对象 五、列表与元组 六、其他 1、格式化输出 2、最大公约数、最小公倍数 3、print、多变量一起定义赋值、end以及列表的方法 4、序列重复、字符串方法、其他列表方法、input 5、字典的方法、ASCII码转换、返回值、修改私人…

MySQL数据库函数——字符函数

目录 引言 常用字符函数表 举例 例子一——工号前加0凑够5位 引言 字符函数&#xff0c;顾名思义就是运用在字符串的函数&#xff0c;下列是一些较为常用的字符函数。 常用字符函数表 函数功能concat&#xff08;S1,S2,.....Sn&#xff09;字符串拼接&#xff0c;将S1&…

算法练习——位运算

前言&#xff1a;位运算的方法大多比较抽象&#xff0c;很难想到。 一&#xff1a;判断字符是否唯一 题目要求&#xff1a; 解题思路&#xff1a; 法一&#xff1a;使用hash的思想&#xff0c;统计每一个字母出现的次数&#xff0c;再通过一次循环遍历查询是否有超过1的字母&…

TCN-Transformer+LSTM多变量回归预测(Matlab)添加气泡图、散点密度图

TCN-TransformerLSTM多变量回归预测&#xff08;Matlab&#xff09;添加气泡图、散点密度图 目录 TCN-TransformerLSTM多变量回归预测&#xff08;Matlab&#xff09;添加气泡图、散点密度图预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基本介绍 1.双路创新&#xff…

【免费分享】mysql笔记,涵盖查询、缓存、存储过程、索引,优化。

概括 本篇笔记涵盖基础查询、视图、存储过程、函数、索引、优化、分库分表。适合在学完mysql后进行时常观看。下面展示部分内容。如果需要可以在文章底部的链接进行下载查看。 简介 数据库 数据库&#xff1a;DataBase&#xff0c;简称 DB&#xff0c;存储和管理数据的仓库…

DataSourceClosedException_ dataSource already closed

修改了项目中kafka相关配置&#xff0c;准备上线&#xff0c;控制台一直报错&#xff1a; 一直不停的在刷数据库连接池已关闭&#xff1f;&#xff1f;&#xff1f; 只改了kafka相关的配置&#xff0c;为什么数据库连接池一直在报错&#xff1f;即使kafka配置写错了&#xff…

SpringCloudAlibaba技术栈-Nacos

1、什么是Nacos&#xff1f; Nacos是个服务中心&#xff0c;就是你项目每个功能模块都会有个名字&#xff0c;比如支付模块,我们先给这个模块起个名字就叫paymentService,然后将这个名字和这个模块的配置放到Nacos中&#xff0c;其他模块也是这样的。好处是这样能更好地管理项…

Java中使用四叶天动态代理IP构建ip代理池,实现httpClient和Jsoup代理ip爬虫

在本次爬虫项目中&#xff0c;关于应用IP代理池方面&#xff0c;具体完成以下功能&#xff1a; 从指定API地址提取IP到ip池中&#xff08;一次提取的IP数量可以自定义更改&#xff09; 每次开始爬虫前&#xff08;多条爬虫线程并发执行&#xff09;&#xff0c;从ip池中获取一…

MySQL 数据库优化详解【Java数据库调优】

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

工业大数据分析算法实战-day15

文章目录 day15特定数据类型的算法工业分析中的数据预处理工况划分数据缺失时间数据不连续强噪声大惯性系统趋势项消除 day15 今天是第15天&#xff0c;昨日是针对最优化算法、规则推理算法、系统辨识算法进行了阐述&#xff0c;今日主要是针对其他算法中的特定数据类型的算法…

定时任务——定时任务技术选型

摘要 本文深入探讨了定时任务调度系统的核心问题、技术选型&#xff0c;并对Quartz、Elastic-Job、XXL-Job、Spring Task/ScheduledExecutor、Apache Airflow和Kubernetes CronJob等开源定时任务框架进行了比较分析&#xff0c;包括它们的特点、适用场景和技术栈。文章还讨论了…

前端遇见AI:打造智能应用的新时代

随着技术的发展&#xff0c;AI&#xff08;人工智能&#xff09;不再局限于后端服务器上运行的复杂算法&#xff0c;而是逐渐渗透到前端领域&#xff0c;成为提升用户体验和应用智能水平的关键因素。本文将探讨前端与AI结合的趋势&#xff0c;以及如何利用前端技术实现AI功能&a…

KNN分类算法 HNUST【数据分析技术】(2025)

1.理论知识 KNN&#xff08;K-Nearest Neighbor&#xff09;算法是机器学习算法中最基础、最简单的算法之一。它既能用于分类&#xff0c;也能用于回归。KNN通过测量不同特征值之间的距离来进行分类。 KNN算法的思想&#xff1a; 对于任意n维输入向量&#xff0c;分别对应于特征…

使用 Three.js 创建一个 3D 人形机器人仿真系统

引言 在这篇文章中&#xff0c;我们将探讨如何使用 Three.js 创建一个简单但有趣的 3D 人形机器人仿真系统。这个机器人可以通过键盘控制进行行走和转向&#xff0c;并具有基本的动画效果。 技术栈 HTML5Three.jsJavaScript 实现步骤 1. 基础设置 首先&#xff0c;我们需要…

Android unitTest 单元测试用例编写(初始)

文章目录 了解测试相关库导入依赖库新建测试文件示例执行查看结果网页结果其他 本片讲解的重点是unitTest&#xff0c;而不是androidTest哦 了解测试相关库 androidx.compose.ui:ui-test-junit4: 用于Compose UI的JUnit 4测试库。 它提供了测试Compose UI组件的工具和API。 and…

【蓝桥杯——物联网设计与开发】拓展模块3 - 温度传感器模块

目录 一、温度传感器模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;STS30-DIS-B &#x1f319;引脚分配 &#x1f319;通信 &#x1f319;时钟拉伸&#xff08;Clock Stretching&#xff09; &#x1f319;单次触发模式 &#x1f319;温度数据转…