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

文章目录

      • 迭代器模式(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.rhkb.cn/news/496036.html

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

相关文章

普通人怎么入门学习并使用AI?

前言 作为普通人看着AI一天一天变革&#xff0c;心急如焚&#xff0c;未来但是就是不知道怎么才算真正进入了AI&#xff0c;使用AI....作为从头至尾追随AI脚步的码农有几点小建议~ 一、&#x1f4bb;使用 AI 网站或软件&#xff0c;解决实际问题 不管用哪种AI&#xff0c;先用…

【Compose multiplatform教程08】【组件】Text组件

查看全部组件https://blog.csdn.net/b275518834/article/details/144751353 Text 功能说明&#xff1a;用于在界面上显示文本内容&#xff0c;支持设置字体、大小、颜色、样式&#xff08;如加粗、斜体、下划线&#xff09;等属性&#xff0c;满足不同的文本展示需求&#xf…

贪心算法(常见贪心模型)

常见贪心模型 简单排序模型 最小化战斗力差距 题目分析&#xff1a; #include <bits/stdc.h> using namespace std;const int N 1e5 10;int n; int a[N];int main() {// 请在此输入您的代码cin >> n;for (int i 1;i < n;i) cin >> a[i];sort(a1,a1n);…

如何通过 360 驱动大师检查自己电脑上的显卡信息

在深入探讨如何查看显卡信息之前&#xff0c;首先需要了解显卡的基本概念。显卡&#xff08;Graphics Processing Unit, GPU&#xff09;&#xff0c;是计算机中负责处理图形输出到显示器的重要硬件。根据其集成度和性能&#xff0c;显卡通常被分为两类&#xff1a; 集成显卡&…

解线性方程组

直接三角分解&#xff08;LU分解&#xff0c;Doolittle分解&#xff09; ATM分解&#xff08;追赶法&#xff0c;Crout分解&#xff0c;克劳特分解&#xff09; 平方根法&#xff08;Cholesky分解&#xff0c;乔列斯基分解&#xff09; 矩阵的范数

实现点击表格中的邀请码并复制到剪贴板的功能

文章目录 实现步骤修改代码1. 添加复制邀请码的处理函数2. 在表格列中添加点击事件3. 添加样式完整的 invite-code-list.vue 文件 要实现点击表格中的邀请码并复制到剪贴板的功能&#xff0c;可以使用 JavaScript 的 Clipboard API。以下是如何在你的 invite-code-list.vue 文…

clickhouse解决suspiciously many的异常

1. 问题背景 clickhouse安装在虚拟机上&#xff0c;持续写入日志时&#xff0c;突然关机&#xff0c;然后重启&#xff0c;会出现clickhouse可以正常启动&#xff0c;但是查询sql语句&#xff0c;提示suspiciously many异常&#xff0c;如图所示 2. 问题修复 touch /data/cl…

本原多项式

将 G F ( p ) GF(p) GF(p)延伸为有 p m p^m pm个元素的域&#xff0c;称之为 G F ( p ) GF(p) GF(p)的扩域&#xff0c;表示为 G F ( p m ) GF(p^m) GF(pm). G F ( p ) GF(p) GF(p)是 G F ( p m ) GF(p^m) GF(pm)的子集。 G F ( p m ) GF(p^m) GF(pm)元素个数为 p m p^m pm。 …

编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法

在编译openssl时 tar -zxvf openssl-1.1.1p.tar.gz cd openssl-1.1.1p ./config --prefix/usr --openssldir/etc/ssl --shared zlib make make test 遇到错误 Parse errors: No plan found in TAP output 解决方法&#xff1a; yum install perl-Test-Simple

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

7.C语言 宏(Macro) 宏定义,宏函数

目录 宏定义 宏函数 1.注释事项 2.注意事项 宏(Macro)用法 常量定义 简单函数实现 类型检查 条件编译 宏函数计算参数个数 宏定义进行类型转换 宏定义进行位操作 宏定义进行断言 总结 宏定义 #include "stdio.h" #include "string.h" #incl…

EdgeX Core Service 核心服务之 Core Command 命令

EdgeX Core Service 核心服务之 Core Command 命令 一、概述 Core-command(通常称为命令和控制微服务)可以代表以下角色向设备和传感器发出命令或动作: EdgeX Foundry中的其他微服务(例如,本地边缘分析或规则引擎微服务)EdgeX Foundry与同一系统上可能存在的其他应用程序…

19_HTML5 Web Workers --[HTML5 API 学习之旅]

HTML5 Web Workers 是一种允许 JavaScript 在后台线程中运行的技术&#xff0c;从而不会阻塞用户界面或其他脚本的执行。通过使用 Web Workers&#xff0c;你可以执行复杂的计算任务而不影响页面的响应速度&#xff0c;提升用户体验。 Web Workers 的特点 Web Workers 是 HTM…

数据分析篇001

目录 一、数据是什么&#xff1f; 二、数据能做什么&#xff1f; 三、数据应用四步骤 第一步---搭建数据体系 第二步---积累数据资产 第三步---完成数据分析 第四步---实现数据应用 四、数据的三种性质 变异性 规律性&#xff08;以正态分布为例&#xff09; 客观性…

Java线程池面试题

为什么要用线程池 降低资源消耗&#xff1a;通过重复利用已创建的线程降低线程创建和销毁造成的消耗提高响应速度&#xff1a;当任务到达时&#xff0c;任务可以不需要等到线程创建就能立即执行方便管理线程&#xff1a;线程是稀缺资源&#xff0c;如果无条件地创建&#xff0…

校史馆云展厅适合远程教学吗?

随着信息技术的飞速发展&#xff0c;远程教学已经成为教育领域的一个重要趋势。 校史馆作为学校文化传承的重要场所&#xff0c;承载着丰富的历史信息和教育资源。 那么&#xff0c;将校史馆搬到云端&#xff0c;构建云展厅&#xff0c;是否适合远程教学呢&#xff1f; 下面…

【安全编码】Web平台如何设计防止重放攻击

我们先来做一道关于防重放的题&#xff0c;答案在文末 防止重放攻击最有效的方法是&#xff08; &#xff09;。 A.对用户密码进行加密存储使用 B.使用一次一密的加密方式 C.强制用户经常修改用户密码 D.强制用户设置复杂度高的密码 如果这道题目自己拿不准&#xff0c;或者…

GJB289A总线典型网络理论分析

1.GJB289A总线典型网络理论分析 根据相关标准&#xff0c;“某个支路的故障不影响整个系统”及耦合变压器特性&#xff0c;本文在仿真与实测时均采用典型的一发一收两端口总线网络。 典型两端口总线网络电气结构如图1所示&#xff0c;包含终端匹配电阻、故障隔离电阻、耦合变…

基于SpringBoot的4S店汽车销售管理系统的设计与实现

一、课题背景 为汽车销售公司设计了一个汽车管理系统 技术&#xff1a;前台采用网页技术&#xff0c;后端采用SpringBoottMybatistvue 项目 描述&#xff1a;随着人们生活水平的不断提高&#xff0c;人们对汽车的消费和需求也越来越旺盛。多汽车销售公司仍然采用人工记账的传…

SQL子查询和having实例

有2个表如下&#xff1b;一个是站点信息&#xff0c;一个是站点不同时间的访问量&#xff0c; 现在要获取总访问量大于200的网站&#xff1b; 先执行如下sql&#xff0c;不包括having子句看一下&#xff0c;获得的是所有站点的总访问量&#xff1b; 这应是一个子查询&#xf…