当前位置: 首页 > news >正文

迭代器模式(Iterator)

迭代器模式是一种行为设计模式,可以在不暴露底层实现(列表、栈或树等)的情况下,遍历一个聚合对象中所有的元素。

Iterator is a behavior design pattern that can traverse all elements of an aggregate object 
without exposing the internal implementation (list, stack, tree, etc.).

结构设计

迭代器模式包含如下角色:
Iterator,迭代器基类,声明遍历聚合对象所需的操作:获取下一个元素、获取当前位置、下一个元素是否存在等。
ConcreteIterator,迭代器实现类,实现遍历聚合对象的算法。
Aggregate,聚合基类,声明一个获取迭代器的接口。
ConcreteAggregate,具体聚合实现类,实现获取一个迭代器的接口并返回一个具体迭代器实例。
Client,客户端,通过聚合基类和迭代器基类的接口与两者进行交互。
迭代器模式类图表示如下:
请添加图片描述

伪代码实现

接下来将使用代码介绍下迭代器模式的实现。

// 1、聚合接口,声明一个获取迭代器的接口,以及元素添加及删除接口
public interface IAggregate {IIterator createIterator();void append(Object element);void removeLast();
}//2、具体聚合实现类,获取一个迭代器的接口,并实现元素添加及删除接口,这里使用数组存储元素
public class ConcreteAggregate implements IAggregate {private String[] elements;private int cursor = -1;public ConcreteAggregate(int size) {elements = new String[size];}@Overridepublic void append(Object element) {cursor++;elements[cursor] = (String) element;}@Overridepublic void removeLast() {elements[cursor] = "";cursor--;}public int getCursor() {return this.cursor;}public String[] getElements() {return this.elements;}@Overridepublic IIterator createIterator() {return new ConcreteIterator(this);}
}// 3、迭代器接口,声明遍历聚合对象所需的操作:获取下一个元素、获取当前位置、下一个元素是否存在等
public interface IIterator {Object first();Object next();boolean hasNext();Object currentItem();
}// 4、迭代器实现类,实现遍历聚合对象的算法,及其他已声明接口
public class ConcreteIterator implements IIterator {private ConcreteAggregate aggregate;private int index;public ConcreteIterator(ConcreteAggregate aggregate) {this.aggregate = aggregate;this.index = 0;}@Overridepublic Object first() {String[] elements = aggregate.getElements();return elements[0];}@Overridepublic Object next() {int cursor = aggregate.getCursor();if (cursor < 0 || index > cursor) {return null;}String[] elements = aggregate.getElements();return elements[index++];}@Overridepublic boolean hasNext() {int cursor = aggregate.getCursor();if (cursor < 0 || index > cursor) {return false;}return true;}@Overridepublic Object currentItem() {int cursor = aggregate.getCursor();if (cursor < 0 || index > cursor) {return null;}String[] elements = aggregate.getElements();return elements[index];}
}// 5、客户端
public class IteratorClient {public void test() {// (1) 创建迭代对象实例IAggregate aggregate = new ConcreteAggregate(10);// (2) 增删元素aggregate.append("hello");aggregate.append("world");aggregate.append("foo");aggregate.removeLast();// (3) 获取迭代器实例IIterator iterator = aggregate.createIterator();// (4) 执行遍历操作while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

适用场景

在以下情况下可以考虑使用迭代器模式:
(1) 当聚合对象的数据结构较复杂,且希望对客户端隐藏其复杂性时(出于易用性或安全性考虑),可考虑使用迭代器模式。迭代器封装了与复杂数据结构进行交互的细节,为客户端提供多个访问集合元素的简单方法。
这种方式不仅对客户端来说非常方便,而且能避免客户端在直接与集合交互时执行错误或有害的操作,从而起到保护集合的作用。
(2) 使用该模式可以减少程序中重复的遍历代码。重要迭代算法的代码往往体积非常庞大。当这些代码被放置在程序业务逻辑中时,它会让原始代码的职责模糊不清,降低其可维护性。因此,
将遍历代码移到特定的迭代器中可使程序代码更加精炼和简洁。
(3) 如果希望代码能够遍历不同的甚至是无法预知的数据结构,可考虑使用迭代器模式。该模式为集合和迭代器提供了一些通用接口。如果在代码中使用了这些接口,那么将其他实现了这些接口的集合和迭代器传递给它时,
它仍将可以正常运行。

优缺点

迭代器模式有以下优点:
(1) 符合单一职责原则。通过将体积庞大的遍历算法代码抽取为独立的类,可对客户端代码和集合进行整理。
(2) 符合开闭原则。可实现新型的集合和迭代器并将其传递给现有代码,无需修改现有代码。
(3) 可以并行遍历同一集合,因为每个迭代器对象都包含其自身的遍历状态。
但是该模式也存在以下缺点:
(1) 如果只与简单的集合进行交互,应用该模式可能会矫枉过正。
(2) 对于某些特殊集合,使用迭代器可能比直接遍历的效率低。
(3) 增加了系统的复杂性。因为迭代器模式将存储数据和遍历数据的职责分离,增加了新的聚合类需要对应增加新的迭代器类,增加了系统的复杂性。

参考

《设计模式 可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英军, 马晓星等译
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/mediator.html 迭代器模式
https://refactoringguru.cn/design-patterns/mediator 迭代器模式
https://www.runoob.com/design-pattern/mediator-pattern.html 迭代器模式
https://www.cnblogs.com/adamjwh/p/10959987.html 简说设计模式——迭代器模式

相关文章:

迭代器模式(Iterator)

迭代器模式是一种行为设计模式&#xff0c;可以在不暴露底层实现(列表、栈或树等)的情况下&#xff0c;遍历一个聚合对象中所有的元素。 Iterator is a behavior design pattern that can traverse all elements of an aggregate object without exposing the internal imple…...

Goland搭建远程Linux开发

Windows和Linux都需要先构建好go环境&#xff0c;启用ssh服务。 打开Windows上的Goland&#xff0c;建立项目。 点击添加配置&#xff0c;选择go构建 点击运行于&#xff0c;选择ssh 填上Linux机器的IP地址和用户名 输入密码 没有问题 为了不让每次运行程序和调试程序都生…...

react中PureComponent的理解与使用

一、作用 它是一个纯组件&#xff0c;会做一个数据的浅比较&#xff0c;当props和state没改变的时候&#xff0c;不会render重新渲染&#xff0c; 改变后才会render重新渲染&#xff0c;提高性能。 二、使用 三、注意 它不能和shouldComponentUpdate生命周期同时使用。因为它…...

洛谷——P5714 【深基3.例7】肥胖问题

文章目录 题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示 AC代码 题目 题目描述 BMI 指数是国际上常用的衡量人体胖瘦程度的一个标准&#xff0c;其算法是 m h 2 \dfrac{m}{h^2} h2m​&#xff0c;其中 m m m 是指体重&am…...

Mac隐藏和显示文件

由于之前没有使用过Mac本&#xff0c;所以很多地方都不太清楚&#xff0c;在下载git项目的时候&#xff0c;发现没有.git文件&#xff0c; 一开始还以为下载错了&#xff0c;但是git命令是可以看到远端分支以及当前分支的&#xff0c;之后在一次解压文件的时候发现&#xff0c;…...

软件工程中应用的几种图辨析

【软件工程】软件工程中应用的几种图辨析&#xff1a;系统流程图、数据流图、数据字典、实体联系图、状态转换图、层次方框图、Warnier图、IPO图、层次图、HIPO图、结构图、程序流程图、盒图、PAD图、判定表_眩晕李的博客-CSDN博客 软件工程——实体关系图 状态转换图 数据流…...

下载离线版的VS Visual Studio 并下载指定的版本

一、先下载引导程序 下载地址VS VisualStudio官网 在这个页面翻到最下面 在这里下载需要的版本 下载引导程序 二、下载离线安装包 写一个批处理文件&#xff08;vs.bat&#xff09; 命令格式如下 <vs引导程序exe> --layout <离线安装包下载的路径> --add <功能…...

Eureka 学习笔记5:InstanceRegistry

版本 awsVersion ‘1.11.277’ LeaseManager 接口管理实例的租约信息&#xff0c;提供以下功能&#xff1a; 注册实例取消注册实例实例续约剔除过期实例 public interface LeaseManager<T> {/** 注册实例并续约*/void register(T r, int leaseDuration, boolean isRep…...

System Verilog——虚方法的使用

1、使用虚方法目的 通过在父类里定义虚方法(task or function)&#xff0c;可以在当父类句柄调用一个方法时候&#xff0c;前提是若是这个句柄指向了子类对象&#xff0c;则调用的方法为子类的方法而不是父类的方法。 1.1、实例理解&#xff1a;将子类句柄赋值成父类句柄 mod…...

线性规划和单纯形法-原理篇

文章目录 引言线性规划标准型问题特点单纯形法 引言 很多运筹学的教材都是从线性规划开始的&#xff0c;我平时做算法策略的落地应用时也研发了一部分基于线性规划的技术方案。可以说&#xff0c;如果搞不懂线性规划&#xff0c;很难成为一名优秀的运筹优化算法工程师。 但是…...

FBX SDK开发快速上手指南

一段时间以来&#xff0c;我一直想制作一个 FBX Exporter 将 FBX 文件转换为我自己的格式。 整个过程不是很顺利&#xff0c;主要是FBX的官方文档不是很清楚。 另外&#xff0c;由于 FBX 格式被许多应用程序使用&#xff0c;而不仅仅是游戏引擎&#xff0c;因此提供的示例代码没…...

探讨|使用或不使用机器学习

动动发财的小手&#xff0c;点个赞吧&#xff01; 机器学习擅长解决某些复杂问题&#xff0c;通常涉及特征和结果之间的困难关系&#xff0c;这些关系不能轻易地硬编码为启发式或 if-else 语句。然而&#xff0c;在决定 ML 是否是当前给定问题的良好解决方案时&#xff0c;有一…...

Git笔记--Ubuntu上传本地项目到github

目录 1--基本配置 2--本地上传 1--基本配置 ① 创建ssh-key cd ~/.sshssh-keygen -t rsa -C "邮箱地址"② 查看并关联ssh-key gedit id_rsa.pub 复制内容&#xff0c;在 GitHub 中依次点击 Settings -> SSH and GPG keys -> New SSH key&#xff0c;将 id…...

基于Go编写一个可视化Navicat本地密码解析器

前提 开发小组在测试环境基于docker构建和迁移一个MySQL8.x实例&#xff0c;过程中大意没有记录对应的用户密码&#xff0c;然后发现某开发同事本地Navicat记录了根用户&#xff0c;于是搜索是否能够反解析Navicat中的密码掩码&#xff08;这里可以基本断定Navicat对密码是采用…...

Maven【入门笔记】

Maven 解决版本依赖的问题 https://www.liaoxuefeng.com/wiki/1252599548343744/1309301146648610 如果没有项目管理工具&#xff0c;在开发项目的时候&#xff0c;我们需要手动管理依赖包&#xff0c;需要管理依赖包的版本、去找到并下载依赖包、还有依赖包所依赖的包 等等。…...

Android Studio中使用cmake开发JNI实战

JNI学习大纲 一、JNI编程入门 二、Android Studio中使用cmake开发JNI实战 第一章节我们介绍了JNI的开发步骤&#xff0c;那这一章节我们就开始在Android Studio中实战一下吧&#xff0c;Lets Start。 1. Android Studio中安装CMake插件 AS中菜单栏选择Tools>SDK Manager在…...

第七章 图论

第七章 图论 一、数据结构定义 图的邻接矩阵存储法#define MaxVertexNum 100 // 节点数目的最大值// 无边权&#xff0c;只用0或1表示边是否存在 bool graph[MaxVertexNum][MaxVertexNum];// 有边权 int graph[MaxVertexNum][MaxVertexNum];图的邻接表存储法 把所有节点存储为…...

IEEE SystemVerilog Chapter13 : Tasks and functions (subroutines)

13.2 Overview 任务和函数提供了从描述中的几个不同位置执行通用过程的能力。它们还提供了一种将大型过程分解为小型过程的方法&#xff0c;以便更容易地阅读和调试源代码描述。本小节讨论了任务和函数之间的区别&#xff0c;描述了如何定义和调用任务和函数&#xff0c;并给出…...

day39反转字符串总结

反转字符串原理其实就是交换位置&#xff0c;以中间为分隔点&#xff1b; 基本套路&#xff1a;遍历前一般字符&#xff0c;互换位置&#xff1b; for循环模板 void reverseString(char* s, int sSize){char temp;for (int i 0, j sSize - 1; i < sSize/2; i, j--) {temp…...

使用Socket实现TCP版的回显服务器

文章目录 1. Socket简介2. ServerSocket3. Socket4. 服务器端代码5. 客户端代码 1. Socket简介 Socket&#xff08;Java套接字&#xff09;是Java编程语言提供的一组类和接口&#xff0c;用于实现网络通信。它基于Socket编程接口&#xff0c;提供了一种简单而强大的方式来实现…...

SenseVoice Small模型可解释性:注意力权重可视化与关键语音片段定位

SenseVoice Small模型可解释性&#xff1a;注意力权重可视化与关键语音片段定位 1. 项目背景与意义 语音识别技术在日常生活中的应用越来越广泛&#xff0c;从智能助手到会议转录&#xff0c;从语音输入到多媒体内容处理&#xff0c;都离不开高效准确的语音转文字服务。Sense…...

GPEN老照片修复案例:增强前后对比,效果直观展示

GPEN老照片修复案例&#xff1a;增强前后对比&#xff0c;效果直观展示 1. 引言&#xff1a;老照片修复的痛点与解决方案 翻开泛黄的相册&#xff0c;那些承载着珍贵记忆的老照片往往因为年代久远而变得模糊、褪色甚至破损。传统的手工修复不仅耗时耗力&#xff0c;还需要专业…...

Gemma-3-12B-IT WebUI保姆级教程:含Supervisord进程守护与开机自启

Gemma-3-12B-IT WebUI保姆级教程&#xff1a;含Supervisord进程守护与开机自启 1. 前言&#xff1a;为什么选择Gemma-3-12B-IT&#xff1f; 如果你正在寻找一个性能强劲、部署友好&#xff0c;而且完全免费开源的大语言模型&#xff0c;那么Google的Gemma-3-12B-IT绝对值得你…...

Pixel Couplet Gen多场景落地:政务公众号/电商首页/校园迎新展板

Pixel Couplet Gen多场景落地&#xff1a;政务公众号/电商首页/校园迎新展板 1. 项目概览 Pixel Couplet Gen是一款基于ModelScope大模型驱动的创新型春联生成工具。与传统春联设计不同&#xff0c;它融合了8-bit像素游戏风格与传统文化元素&#xff0c;创造出独特的数字春节…...

Pixel Couplet Gen完整指南:从GitHub Fork到微信小程序上线的像素春联项目闭环

Pixel Couplet Gen完整指南&#xff1a;从GitHub Fork到微信小程序上线的像素春联项目闭环 1. 项目介绍与核心价值 Pixel Couplet Gen是一款融合AI技术与复古游戏美学的创新应用&#xff0c;它将传统春联创作带入了数字时代。这个项目最吸引人的特点是&#xff1a; 8-bit像素…...

别再只盯着真值了!用AirSim API实战:如何正确解析无人机状态数据(附Python代码)

别再只盯着真值了&#xff01;用AirSim API实战&#xff1a;如何正确解析无人机状态数据&#xff08;附Python代码&#xff09; 当你第一次从AirSim获取无人机状态数据时&#xff0c;可能会被返回的复杂字典结构弄得一头雾水。那些嵌套的Vector3r和Quaternionr对象&#xff0c;…...

Elixir Plug安全防护:CSRF保护、SSL强制与基础认证的终极教程

Elixir Plug安全防护&#xff1a;CSRF保护、SSL强制与基础认证的终极教程 【免费下载链接】plug Compose web applications with functions 项目地址: https://gitcode.com/gh_mirrors/pl/plug Elixir Plug 是一个强大的 Web 应用构建工具&#xff0c;提供了全面的安全防…...

为什么99%的Python团队还没用上AOT?2026年官方方案的3大硬伤与2个绕过技巧(含patch diff与CI集成脚本)

第一章&#xff1a;Python 原生 AOT 编译方案 2026 概览与演进脉络Python 长期以来以解释执行和 JIT 辅助&#xff08;如 PyPy&#xff09;为主流运行范式&#xff0c;而原生 Ahead-of-Time&#xff08;AOT&#xff09;编译在 2026 年迎来实质性突破&#xff1a;CPython 官方正…...

老马失前蹄,竟然在数据库外键上翻车了,重温外键级联

一、什么是setuptools&#xff1f; setuptools 是一个用于创建、分发和安装 Python 包的核心库。 它可以帮助你&#xff1a; 定义 Python 包的元数据&#xff08;如名称、版本、作者等&#xff09;。 声明包的依赖项&#xff0c;确保你的包能够正确运行。 构建源代码分发包&…...

PasteMD用户调研报告:2024年文档格式转换需求分析

PasteMD用户调研报告&#xff1a;2024年文档格式转换需求分析 1. 调研背景与核心发现 最近整理了500份来自不同行业用户的实际反馈&#xff0c;这些反馈不是问卷里的标准答案&#xff0c;而是真实工作场景中留下的痕迹——有深夜赶论文时的抱怨截图&#xff0c;有项目汇报前的…...