迭代器模式的理解和实践

引言

        在软件开发中,我们经常需要遍历容器对象(如数组、列表、集合等)中的元素。如果每个容器对象都实现自己的遍历算法,那么代码将会变得冗余且难以维护。为了解决这个问题,迭代器模式应运而生。迭代器模式是一种行为型设计模式,它提供了一种统一的方法来访问容器对象中的元素,而无需暴露容器的内部结构。本文将详细讲解迭代器模式的概念、原理及其在Java中的实践应用。

 

一、迭代器模式概述

1.1 定义

        迭代器模式(Iterator Pattern)又称为游标模式,是一种行为型设计模式。它提供了一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。迭代器模式使得用户可以通过一致的接口访问不同聚合对象中的元素,而无需了解聚合对象的内部结构。

1.2 结构

        迭代器模式主要包含以下角色:

  • 迭代器(Iterator):定义访问和遍历元素的接口,通常包含 hasNext() 和 next() 方法。
  • 具体迭代器(ConcreteIterator):实现迭代器接口,并要记录遍历中的当前位置。
  • 聚合(Aggregate):也称为容器,负责提供创建具体迭代器角色的接口,通常是一个接口或抽象类,包含一个 iterator() 方法。
  • 具体聚合(ConcreteAggregate):实现聚合接口,返回具体的迭代器实例。
  • 客户端(Client):使用迭代器遍历聚合对象中的元素。

1.3 原理

        迭代器模式的原理是将集合对象的遍历逻辑从集合类中分离出来,封装在独立的迭代器类中。这样,客户端可以通过迭代器接口访问集合中的元素,而无需知道集合的内部结构。同时,迭代器类可以根据不同的集合实现不同的遍历算法,从而提供灵活的遍历方式。

二、迭代器模式的优点和缺点

2.1 优点

  • 简化集合接口:迭代器承担了遍历集合的职责,使得集合接口更加简洁,只关注元素的添加、删除等操作。
  • 支持多种遍历方式:可以为不同的需求定制不同的迭代器,如正向迭代器、反向迭代器、过滤器迭代器等。
  • 统一访问方式:无论集合结构如何变化,迭代器为访问提供一致的接口,用户无需改变遍历代码。
  • 提高代码复用性:迭代器模式使得相同的遍历算法可以在不同的集合上重复使用。

2.2 缺点

  • 性能问题:创建迭代器可能带来额外的资源消耗,尤其是在集合较小或遍历操作较简单时。
  • 复杂度增加:对于简单的遍历需求,直接使用循环可能更简单明了。引入迭代器模式可能会增加代码的复杂度。
  • 迭代器失效:如果集合在迭代过程中被修改(如添加、删除元素),可能会导致迭代器失效。解决策略可能包括在迭代器失效时抛出异常,或在集合类中进行操作时自动更新迭代器。

三、迭代器模式的实践

        下面我们以一个简单的书籍集合为例,演示如何使用迭代器模式遍历集合中的元素。

3.1 定义书籍类和书籍集合

        首先,我们定义一个书籍类 Book 和一个书籍集合接口 BookShelf。书籍集合接口包含一个 iterator() 方法,用于返回迭代器实例。

// 书籍类
public class Book {private String name;public Book(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}// 书籍集合接口
public interface BookShelf {Iterator<Book> iterator();
}


3.2 实现具体书籍集合和迭代器

        接下来,我们实现一个具体的书籍集合 ConcreteBookShelf 和一个具体的迭代器 BookShelfIterator

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;// 具体书籍集合
public class ConcreteBookShelf implements BookShelf {private List<Book> books = new ArrayList<>();public void addBook(Book book) {this.books.add(book);}public List<Book> getBooks() {return books;}@Overridepublic Iterator<Book> iterator() {return new BookShelfIterator(this);}
}// 具体迭代器
public class BookShelfIterator implements Iterator<Book> {private ConcreteBookShelf bookShelf;private int index;public BookShelfIterator(ConcreteBookShelf bookShelf) {this.bookShelf = bookShelf;this.index = 0;}@Overridepublic boolean hasNext() {return index < bookShelf.getBooks().size();}@Overridepublic Book next() {if (hasNext()) {return bookShelf.getBooks().get(index++);}throw new RuntimeException("No more elements in the iteration");}
}


3.3 客户端代码

        最后,我们编写客户端代码,使用迭代器遍历书籍集合中的元素。

public class Client {public static void main(String[] args) {ConcreteBookShelf bookShelf = new ConcreteBookShelf();bookShelf.addBook(new Book("Around the World in 80 Days"));bookShelf.addBook(new Book("Bible"));bookShelf.addBook(new Book("Cinderella"));bookShelf.addBook(new Book("Daddy-Long-Legs"));bookShelf.addBook(new Book("White-Rich-Beautiful"));Iterator<Book> iterator = bookShelf.iterator();while (iterator.hasNext()) {Book book = iterator.next();System.out.println(book.getName());}}
}


3.4 运行结果

        运行客户端代码,输出结果为:

Around the World in 80 Days
Bible
Cinderella
Daddy-Long-Legs
White-Rich-Beautiful


四、迭代器模式的应用场景

        迭代器模式在实际开发中有很多应用场景,以下是一些常见的例子:

  • 集合类:如Java中的List、Set、Map等集合类都实现了迭代器模式,提供了统一的遍历接口。
  • 菜单系统:在GUI应用程序中,菜单项通常存储在一个集合中。使用迭代器模式可以方便地遍历菜单项,并根据需要执行相应的操作。
  • 文件系统:在文件系统中,文件和目录通常组织成一个树状结构。使用迭代器模式可以遍历文件系统树,查找文件或目录。
  • 数据库查询结果:数据库查询结果通常返回一个结果集对象。使用迭代器模式可以遍历结果集中的每一行数据,并进行处理。

总结

        迭代器模式是一种强大的设计模式,它提供了一种统一的方法来访问容器对象中的元素,而无需暴露容器的内部结构。通过将遍历逻辑封装在独立的迭代器类中,迭代器模式简化了集合接口,支持多种遍历方式,并提高了代码的复用性。同时,迭代器模式也存在一些缺点,如性能问题和复杂度增加等。在实际开发中,我们需要根据具体需求权衡利弊,选择合适的设计模式来实现功能。希望本文能帮助你理解迭代器模式,并通过具体的Java代码示例掌握其实现方法。

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

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

相关文章

TS2339: Property ‘value‘ does not exist on type ‘MessageBoxData‘.

1、源代码 <template><el-dialog:visible"visible":before-close"handleClose":close-on-click-modal"false"title"邀请码"width"1200px"append-to-bodydestroy-on-close><div class"invite-code-wrap…

ubuntu防火墙(三)——firewalld使用与讲解

本文是Linux下&#xff0c;用ufw实现端口关闭、流量控制(二) firewalld使用方式 firewalld 是一个动态管理防火墙的工具&#xff0c;主要用于 Linux 系统&#xff08;包括 Ubuntu 和 CentOS 等&#xff09;。它提供了一个基于区域&#xff08;zones&#xff09;和服务&#x…

Windows 安装配置 RabbitMQ 详解

博主介绍&#xff1a; 计算机科班人&#xff0c;全栈工程师&#xff0c;掌握C、C#、Java、Python、Android等主流编程语言&#xff0c;同时也熟练掌握mysql、oracle、sqlserver等主流数据库&#xff0c;能够为大家提供全方位的技术支持和交流。 工作五年&#xff0c;具有丰富的…

R语言的数据结构--矩阵

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言医学数据分析实践-R语言的数据结构-CSDN博客 矩阵是一个二维数组&#xff0c;矩阵中的元素都具有相…

JAVA基础学习笔记_反射+动态代理

文章目录 反射获取class对象的三种方式获取构造方法获取成员变量获取成员方法反射的作用 动态代理 反射 允许对成员变量\成员方法\构造方法的信息进行编程访问 把类内的信息扒的干干净净,获取解剖 获取从class字节码文件中获取 获取class对象的三种方式 public static void …

微信小程序一键复制功能

wx.setClipboardData(Object object) 设置系统剪贴板的内容。调用成功后&#xff0c;会弹出 toast 提示"内容已复制"&#xff0c;持续 1.5s wx.setClipboardData({data: 你需要复制的内容,success (res) {wx.getClipboardData({success (res) {console.log(res.dat…

【Python网络爬虫 常见问题汇总】

目录 1. 爬取图片出现403解决办法&#xff1a;设置请求头中的Referer字段 2.关于干坏事的问题后续不定期更新 欢迎共同探讨学习进步 1. 爬取图片出现403 问题出自案例9&#xff0c;已解决。 【Python网络爬虫笔记】9- 抓取优美图库高清壁纸 当在爬取图库图片时遇到 403 错误…

Linux: docker: 怎么修改 proc下的文件内容?

文章目录 参考问题方法 1:在宿主机上修改参数方法 2:启动容器时挂载 /proc 为可写方法 3:通过 Kubernetes 调整配置方法 4:构建特权容器参考 https://docs.docker.com/security/for-admins/hardened-desktop/enhanced-container-isolation/features-benefits/#procfs–sys…

分布式 分布式事务 总结

前言 相关系列 《分布式 & 目录》《分布式 & 分布式事务 & 总结》《分布式 & 分布式事务 & 问题》 分布式事务 所谓分布式事务是指操作范围笼罩多个不同节点的事务。例如对于订单节点&库存节点而言&#xff0c;一次完整的交易需要同时调动两个节…

STM32+模拟或硬件IIC+SHT20驱动问题:接上拉电阻、BUSY死锁?

主要问题&#xff1a; 1&#xff0c;使用STM32F103C8T6&#xff0c;模拟IIC&#xff0c;SCL和SDA口配置为推挽输出上拉&#xff0c;主要是SDA脚&#xff0c;每次都要输出输入模式重新配置&#xff0c;虽然也能通信&#xff0c;但不稳定&#xff0c;出错率大&#xff1b; 2&…

【工业机器视觉】基于深度学习的水表盘读数识别(3-数据标注与转换)

【工业机器视觉】基于深度学习的仪表盘识读&#xff08;2&#xff09;-CSDN博客 数据标注 标注扩展 Labelme 和 LabelImg 都是用于创建机器学习和计算机视觉项目所需标注数据的工具。它们都允许用户通过图形界面手动标注图像&#xff0c;但各自有其特点和适用场景。 Labelme…

静态路由与交换机配置实验

1.建立网络拓扑 添加2台计算机&#xff0c;标签名为PC0、PC1&#xff1b;添加2台二层交换机2960&#xff0c;标签名为S0、S1&#xff1b;添加2台路由器2811&#xff0c;标签名为R0、R1&#xff1b;交换机划分的VLAN及端口根据如下拓扑图&#xff0c;使用直通线、DCE串口线连接…

【Spark】Spark Join类型及Join实现方式

Spark Join类型 1. Inner Join (内连接) 示例&#xff1a;val result df1.join(df2, df1("id") df2("id"), "inner")执行逻辑&#xff1a;只返回那些在两个表中都有匹配的行。 2. Left Join (左外连接) 示例&#xff1a;val result df1.jo…

socket UDP 环路回显的服务端

基于socket通讯的方式&#xff0c;无论用http或者udp或者自定义的协议&#xff0c;程序结构都是类似的。这个以UDP协议为例简要说明。 #include <stdio.h> // 标准输入输出库 #include <sys/types.h> // 提供了一些数据类型&#xff0c;如ssize_t #include <sy…

Linux:network:添加ip的时候自动添加一个本地路由

文章目录 问题问题 最近在看一个路由的问题,顺便看内核代码,发现在添加IP的时候,内核会自动添加一个local route。 net/ipv4/devinet.c inet_rtm_newaddr->__inet_insert_ifa /* Send message first, then call notifier.Notifier will trigger FIB update, so thatlis…

Magnet Player:一款基于Web的磁力链媒体播放器

Magnet Player&#xff1a;一款基于Web的磁力链媒体播放器 项目地址:https://gitcode.com/gh_mirrors/ma/magnet-player 是一个创新的开源项目&#xff0c;它允许用户直接在浏览器中播放磁力链&#xff08;Magnet URI&#xff09;内容&#xff0c;无需下载或安装任何桌面应用…

php:完整部署Grid++Report到php项目,并实现模板打印

一、下载Grid++Report软件 路径:开发者安装包下载 - 锐浪报表工具 二、 安装软件 1、对下载的压缩包运行内部的exe文件 2、选择语言 3、 完成安装引导 下一步即可 4、接收许可协议 点击“我接受” 5、选择安装路径 “浏览”选择安装路径,点击"安装" 6、完成…

web安全攻防入门教程

Web安全攻防入门教程 Web安全攻防是指在Web应用程序的开发、部署和运行过程中&#xff0c;保护Web应用免受攻击和恶意行为的技术与策略。这个领域不仅涉及防御措施的实现&#xff0c;还包括通过渗透测试、漏洞挖掘和模拟攻击来识别潜在的安全问题。 本教程将带你入门Web安全攻…

前端node环境安装:nvm安装详细教程(安装nvm、node、npm、cnpm、yarn及环境变量配置)

需求&#xff1a;在做前端开发的时候&#xff0c;有的时候 这个项目需要 node 14 那个项目需要 node 16&#xff0c;我们也不能卸载 安装 。这岂不是很麻烦。这个时候 就需要 一个工具 来管理我们的 node 版本和 npm 版本。 下面就分享一个 nvm 工具 用来管理 node 版本。 这个…

Unity在运行状态下,当物体Mesh网格发生变化时,如何让MeshCollider碰撞体也随之实时同步变化?

旧版源代码地址&#xff1a;https://download.csdn.net/download/qq_41603955/90087225?spm1001.2014.3001.5501 旧版效果展示&#xff1a; 新版加上MeshCollider后的效果&#xff1a; 注意&#xff1a;在Unity中&#xff0c;当你动态地更改物体的Mesh时&#xff0c;通常期望…