【设计模式】迭代器模式 (游标(Cursor)模式)

迭代器模式(Iterator Pattern)详解


一、迭代器模式简介

迭代器模式(Iterator Pattern) 是一种 行为型设计模式(对象行为型模式),它提供了一种方法来顺序访问一个聚合对象中的各个元素,而无需暴露该对象的内部表示。换句话说,迭代器模式使得客户端可以通过统一的方式来遍历不同的集合类型(如数组、链表等),同时不需要了解这些集合的内部结构。

你可以把它想象成电视遥控器上的“下一个频道”按钮,无论你当前在观看哪个频道,按下这个按钮都会带你去到下一个频道,而你并不需要知道电视台是如何排列这些频道的。

在这里插入图片描述
电视机 <- -> 存储电视频道的集合 <- -> 聚合类(Aggregate Classes)
电视机遥控器 <- -> 操作电视频道 <- -> 迭代器(Iterator)
访问一个聚合对象中的元素但又不需要暴露它的内部结构

聚合对象的两个职责

  1. 存储数据,聚合对象的基本职责
  2. 遍历数据,既是可变化的,又是可分离的

将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中
由迭代器来提供遍历聚合对象内部数据的行为,简化聚合对象的设计,更符合单一职责原则

迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,且不用暴露该对象的内部表示。

又名**游标(Cursor)**模式。

通过引入迭代器,客户端无须了解聚合对象的内部结构即可实现对聚合对象中成员的遍历,还可以根据需要很方便地增加新的遍历方式。

迭代器模式包含以下4个角色

Iterator(抽象迭代器)
ConcreteIterator(具体迭代器)
Aggregate(抽象聚合类)
ConcreteAggregate(具体聚合类)

在这里插入图片描述


二、解决的问题类型

迭代器模式主要用于解决以下问题:

  • 不同数据结构的遍历方式不一致:比如数组和链表有不同的遍历方式。
  • 希望隐藏容器的内部实现细节:使客户端代码与具体的容器实现解耦。
  • 支持多种遍历方式:例如前序遍历、中序遍历、后序遍历等。
  • 为遍历不同的聚合结构提供一个统一的接口:在该接口的实现类中为不同的聚合结构提供不同的遍历方式,而客户端可以一致性地操作该接口。
  • 访问一个聚合对象的内容而无须暴露它的内部表示

三、使用场景

场景示例
集合类库Java 的 ArrayList, HashSet 等都实现了 Iterable 接口
自定义集合类当你需要为自定义的数据结构提供遍历功能时
复杂数据结构如树形结构或图结构

四、核心概念

  1. Iterator(迭代器接口):定义了遍历操作的方法,如 hasNext(), next(), 和可选的 remove()
  2. ConcreteIterator(具体迭代器):实现了 Iterator 接口,负责管理当前遍历的位置。
  3. Aggregate(聚合接口):定义了创建迭代器对象的方法 createIterator()
  4. ConcreteAggregate(具体聚合类):实现了 Aggregate 接口,返回一个 ConcreteIterator 实例。

五、实际代码案例(Java)

1. 定义 Iterator 接口

// 迭代器接口
public interface Iterator<T> {boolean hasNext();T next();
}

2. 定义 ConcreteIterator 类

// 具体迭代器类
class NameIterator implements Iterator<String> {private String[] names;private int position = 0;public NameIterator(String[] names) {this.names = names;}@Overridepublic boolean hasNext() {return position < names.length;}@Overridepublic String next() {if (this.hasNext()) {return names[position++];} else {return null;}}
}

3. 定义 Aggregate 接口

// 聚合接口
public interface Aggregate {Iterator createIterator();
}

4. 定义 ConcreteAggregate 类

// 具体聚合类
class NameCollection implements Aggregate {private String[] names;public NameCollection(String[] names) {this.names = names;}@Overridepublic Iterator createIterator() {return new NameIterator(names);}
}

5. 客户端测试类

public class Client {public static void main(String[] args) {String[] names = {"Alice", "Bob", "Charlie"};Aggregate collection = new NameCollection(names);Iterator iterator = collection.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

输出结果:

Alice
Bob
Charlie
典型代码

典型的抽象迭代器代码

interface Iterator
{void First(); //将游标指向第一个元素void Next(); //将游标指向下一个元素bool HasNext(); //判断是否存在下一个元素object CurrentItem(); //获取游标指向的当前元素
}

典型的具体迭代器代码

class ConcreteIterator : Iterator
{private ConcreteAggregate objects; //维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据private int cursor; //定义一个游标,用于记录当前访问位置public ConcreteIterator(ConcreteAggregate objects) {this.objects = objects;}public void First() {  //实现代码  }	public void Next() { //实现代码  }public bool HasNext() {  //实现代码}	public object CurrentItem(){  //实现代码}
}

典型的抽象聚合类代码

interface Aggregate
{Iterator CreateIterator();
}

典型的具体聚合类代码

class ConcreteAggregate : Aggregate 
{......public Iterator CreateIterator() {return new ConcreteIterator(this);}......
}
其他案例
  1. 某软件公司为某商场开发了一套销售管理系统,在对该系统进行分析
    AbstractObjectList类的方法与说明
    在这里插入图片描述
    AbstractObjectList类的子类ProductList和CustomerList分别用于存储商品数据和客户数据。
    通过分析,发现AbstractObjectList类的职责非常重,它既负责存储和管理数据,又负责遍历数据,违背了单一职责原则,实现代码将非常复杂。因此,开发人员决定使用迭代器模式对AbstractObjectList类进行重构,将负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历分离,还可以给不同的具体数据集合类提供不同的遍历方式。
    现给出使用迭代器模式重构后的解决方案。

在这里插入图片描述

  1. 电视机遥控器
    电视机遥控器就是一个迭代器的实例,通过它可以实现对电视机频道集合的遍历操作,本实例我们将模拟电视机遥控器的实现。

在这里插入图片描述


六、优缺点分析

优点描述
简化了集合的遍历过程提供了一致的遍历接口,便于维护和扩展,
封装性良好隐藏了集合的内部结构,增强了安全性,简化了聚合类
支持多种遍历方式可以为同一集合提供不同的迭代器实现,在同一个聚合对象上可以定义多种遍历方式
其他由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,符合开闭原则
缺点描述
增加了系统复杂度对于简单的集合遍历需求,引入迭代器模式可能显得过于复杂。在增加新的聚合类时需要对应地增加新的迭代器类,类的个数成对增加。
性能开销创建迭代器实例会带来额外的内存消耗
其他抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是一件很容易的事情

七、与其他模式对比(补充)

模式名称目标
组合模式处理树形结构的遍历
观察者模式当对象状态变化时通知其他对象
迭代器模式提供统一的遍历接口

八、最终小结

迭代器模式是一种非常实用的设计模式,特别适用于那些需要对不同类型的数据集合进行遍历操作的场景。通过应用迭代器模式,我们不仅能够简化集合的遍历逻辑,还能有效地将集合的具体实现细节与遍历算法分离,从而提高代码的灵活性和可维护性。


📌 一句话总结:

迭代器模式就像一个通用的遥控器,无论你的电视节目单(集合)如何组织,都能按顺序播放每一个节目(元素)。


推荐使用方式:

  • 在需要对多种类型的集合进行遍历时;
  • 希望保持集合类的封装性,不让外部直接访问其内部结构时;
  • 支持多种遍历策略时。

部分内容由AI大模型生成,注意识别!

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

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

相关文章

docker安装 Elasticsearch、Kibana、IK 分词器

Elasticsearch 1.拉去镜像 docker pull elasticsearch:8.12.2 docker pull kibana&#xff1a;8.12.22.创建挂载目录 mkdir /root/elasticsearch3.不挂载启动 docker run -d \ --restartalways \ --name fusion_elasticsearch \ --network fusion_network \ -p 9200:9200 \ -p …

Java面试宝典:Spring专题二

一、介绍下Spring中的事务 1.Spring事务的本质与价值 Spring事务本质是基于AOP的声明式事务封装,通过代理机制在目标方法前后注入事务管理逻辑(开启、提交/回滚)。其核心价值在于: 业务解耦:将事务控制从业务代码剥离,通过配置或注解管理(如@Transactional)。 统一抽…

DGMR压缩技术:让大规模视觉Transformer模型体积减半而性能不减

Transformer架构展现出卓越的扩展特性&#xff0c;其性能随模型容量增长而持续提升。大规模模型在获得优异性能的同时&#xff0c;也带来了显著的计算和存储开销。深入分析主流Transformer架构发现&#xff0c;多层感知器&#xff08;MLP&#xff09;模块占据了模型参数的主要部…

JavaWeb学习打卡14(JSP内置对象及作用域)

JSP 中9 大内置对象PageContext // 用来存东西Request // 用来存东西ResponseSession // 用来存东西Application &#xff08;ServletContext&#xff09; // 用来存东西config &#xff08;ServletConfig&#xff09;outpage…

涛思数据参与起草中国工业互联网研究院《工业数据库规范》全系列标准

最近&#xff0c;《工业数据库规范》系列团体标准正式发布。该标准由中国工业互联网研究院牵头&#xff0c;中国移动通信联合会发布&#xff0c;共分为三部分—— 第1部分&#xff1a;云数据库第2部分&#xff1a;实时数据库第3部分&#xff1a;时序数据库 涛思数据作为三项标…

使用exceljs导出luckysheet表格 纯前端 支持离线使用

一.技术 exceljs&#xff0c;luckysheet 二.实现 参考网上博文exceljs对导出lucksheet表格的实现,发现存在一些问题并给予修复: 1.字体颜色、字号&#xff0c;加粗等适配的问题. 2.单元格对齐方式不生效; 3.单元格边框无法绘制; 4.单元格边框颜色及线型错乱; 5.单元格列…

从0到1学习c++ 命名空间

也是好久没写博客了&#xff0c;主播这半年一直在忙别的领域&#xff0c;在磁力驱动领域干了一年&#xff0c;最好发现自己对这个领域并不是很感兴趣&#xff0c;做这个领域多半都是为了发文章&#xff0c;现在闲下来了&#xff0c;主播终于也是过上好日子了&#xff0c;主播又…

大模型提示词漏洞攻防测试:技术分析与实践指南

引言 随着ChatGPT、Claude、Gemini等大型语言模型(LLMs)的广泛应用&#xff0c;它们已经成为现代AI系统的核心组件&#xff0c;被整合到各种产品和服务中。这些模型通过提示。Prompts)与用户进行交互&#xff0c;而提示词作为人类与AI沟通的桥梁&#xff0c;其安全性变得尤为重…

Golang实现 - 实现只有表头的 Excel 模板,并在指定列添加了下拉框功能。生成的 Excel 文件在打开时,指定列的单元格会显示下拉选项

该版本完全兼容最新版 excelize 库 (v2.7)&#xff0c;实现了只有表头的 Excel 模板&#xff0c;并在指定列添加了下拉框功能。生成的 Excel 文件在打开时&#xff0c;指定列的单元格会显示下拉选择箭头。代码如下&#xff1a;package mainimport ("fmt""log&qu…

全连接队列

监听套接字使用socket接口创建一个套接字&#xff0c;然后bind给套接字绑定地址&#xff0c;最后listen将套接字设置为监听套接字。监听套接字以前理解是三元组标识&#xff0c;后面看了netstat&#xff0c;觉得应该是五元组&#xff0c;只不过它这个五元组是{协议&#xff0c;…

JavaWeb-JSP

JSP JSP就是模板引擎 Template&#xff0c;因为看到的jsp是模板不变的&#xff0c;如果想让页面发生改变&#xff0c;就是自己添加java代码改变页面。有Java代码&#xff0c;Tomcat服务器就会对jsp模板进行解析&#xff0c;解析完之后就是Servlet&#xff08;java类&#xff09…

大模型中常说的Token到底是什么?和Cookie和Session有什么区别?一文讲清

什么是Token&#xff08;令牌&#xff09;Acesss Token是访问资源接口&#xff08;API&#xff09;时所需要的资源凭证。简单token的组成&#xff1a;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign&#xff08;签名&#xff0c;token的前几位以哈希算法压缩成的一定长…

RAGFlow:检索增强生成技术的高效实现与深度探索

在当今信息爆炸的时代&#xff0c;如何从海量的数据中快速、准确地获取并利用有价值的信息&#xff0c;成为了众多领域面临的关键挑战。检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;技术应运而生&#xff0c;它将信息检索与大型语言模型&#xff…

【轨物洞见】光伏逆变器数据:分布式电站价值回归的“第一块多米诺骨牌”

1. 逆变器&#xff1a;光伏电站的核心“数据心脏” 逆变器是将光伏组件产生的直流电转换为交流电的关键设备&#xff0c;其性能直接影响着整个电站的效率与稳定性。对其电压、电流、功率参数以及故障告警信息进行远程数据采集&#xff0c;是实现精细化运维和预测性维护的起点。…

如何在 npm 上发布 Element Plus 二次封装组件

在一次开发中&#xff0c;小李接到一个重要的任务&#xff1a;将 Element Plus 中的时间组件根据团队的独特需求进行二次封装。他灵机一动&#xff0c;决定将这个自定义组件打包成一个 npm 包&#xff0c;以便团队的其他小伙伴们可以快速、方便地使用。接下来&#xff0c;让我们…

vue2使用v-viewer图片预览:打开页面自动预览,禁止关闭预览,解决在微信浏览器的页面点击事件老是触发预览初始化的问题

1、安装&#xff1a; npm install v-viewer viewerjs2、在 main.js 中全局注册&#xff1a; import Viewer from v-viewer; import viewerjs/dist/viewer.css; Vue.use(Viewer ); //配置项&#xff08;可选&#xff0c;根据需求调整&#xff09; // Vue.use(Viewer, { // d…

开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

无线通信资源分配相关算法

1.Maximum Clique First (MCF)是一种启发式图着色算法&#xff08;heuristic graph coloring algorithm&#xff09;&#xff0c;它的核心思想是&#xff1a;优先为图中最大团&#xff08;maximum clique&#xff09;中的顶点分配不同的颜色&#xff0c;然后再依次为其他顶点上…

Kafka监控体系搭建:基于Prometheus+JMX+Grafana的全方位性能观测方案

为什么需要Kafka监控监控架构概述步骤一&#xff1a;部署JMX Exporter 1.1 下载JMX Agent1.2 创建指标暴露配置 步骤二&#xff1a;配置Kafka集成JMX 2.1 启动参数配置2.2 验证指标暴露 步骤三&#xff1a;配置Prometheus采集 3.1 修改Prometheus配置3.2 验证数据采集 步骤四&a…

stack 和 queue

目录 一、stack 1.1 stack 的介绍 1.2 stack的使用 1&#xff09;最小栈 2&#xff09;栈的弹出压入序列 3&#xff09;逆波兰表达式求值 1.3 stack 的模拟使用 二、queue 2.1 queue的介绍 2.2 queue的使用 2.3 queue的模拟使用 三、容器适配器 3.1 什么是容器适配…