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

迭代器模式介绍

目录

一、迭代器模式介绍

1.1 迭代器模式定义

1.2 迭代器模式原理

1.2.1 迭代器模式类图

1.2.2 模式角色说明

1.2.3 示例代码

二、迭代模式的应用

2.1 需求说明

2.2 需求实现

2.2.1 抽象迭代类

2.2.2 抽象集合类

2.2.3 主题类

2.2.4 具体迭代类

2.2.5 具体集合类

2.2.6 测试类

三、迭代器模式总结

3.1 迭代器模式的优点

3.2 迭代器模式的缺点

3.3 迭代器模式的使用场景


一、迭代器模式介绍

1.1 迭代器模式定义

迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各个元素进行访问的方法,而又不需要暴露该对象的内部细节。

迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中,迭代器已经成为一个基础的类库,直接用来遍历集合对象。在平时开发中,我们更多的是直接使用它,很少会从零去实现一个迭代器。

在软件系统中,容器对象拥有两个职责:一是存储数据,而是遍历数据。从依赖性上看,前者是聚合对象的基本职责。而后者是可变化的,又是可分离的。因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则。

1.2 迭代器模式原理

1.2.1 迭代器模式类图

1.2.2 模式角色说明

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

  • 抽象集合(Aggregate)角色:用于存储和管理元素对象, 定义存储、添加、删除集合元素的功能,并且声明了一个createIterator()方法用于创建迭代器对象。
  • 具体集合(ConcreteAggregate)角色:实现抽象集合类,返回一个具体迭代器的实例。
  • 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含hasNext()、next() 等方法。
  1. hasNext()函数用于判断集合中是否还有下一个元素。
  2. next() 函数用于将游标后移一位元素。
  3. currentItem() 函数,用来返回当前游标指向的元素。
  • 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对集合对象的遍历,同时记录遍历的当前位置。

1.2.3 示例代码

package main.java.cn.test.iterator.V1;/*** @author ningzhaosheng* @date 2024/1/15 15:23:06* @description 迭代器接口*/
public interface Iterator<E> {//判断集合中是否有下一个元素boolean hasNext();//将游标后移一位元素void next();//返回当前游标指定的元素E currentItem();
}
package main.java.cn.test.iterator.V1;import java.util.ArrayList;
import java.util.NoSuchElementException;/*** @author ningzhaosheng* @date 2024/1/15 15:23:43* @description 具体迭代器*/
public class ConcreteIterator<E> implements Iterator<E> {//游标private int cursor;//容器private ArrayList<E> arrayList;public ConcreteIterator(ArrayList<E> arrayList) {this.cursor = 0;this.arrayList = arrayList;}@Overridepublic boolean hasNext() {return cursor != arrayList.size();}@Overridepublic void next() {cursor++;}@Overridepublic E currentItem() {if (cursor >= arrayList.size()) {throw new NoSuchElementException();}return arrayList.get(cursor);}
}
package main.java.cn.test.iterator.V1;import java.util.ArrayList;/*** @author ningzhaosheng* @date 2024/1/15 15:25:35* @description 测试类*/
public class Test {public static void main(String[] args) {ArrayList<String> names = new ArrayList<>();names.add("lisi");names.add("zhangsan");names.add("wangwu");Iterator<String> iterator = new ConcreteIterator(names);while (iterator.hasNext()) {System.out.println(iterator.currentItem());iterator.next();}/*** 使用ArrayList集合中的iterator()方法获取迭代器* 将创建迭代器的方法放入集合容器中,这样做的好处是对客户端封装了迭代器的实现细节.*/java.util.Iterator<String> iterator1 = names.iterator();while (iterator1.hasNext()) {System.out.println(iterator1.next());iterator.next();}}
}

二、迭代模式的应用

2.1 需求说明

为了帮助大家更好地理解迭代器模式,下面我还是通过一个简单的例子给大家演示一下

2.2 需求实现

2.2.1 抽象迭代类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:30:18* @description 抽象迭代器 IteratorIterator*/
public interface IteratorIterator<E> {//重置为第一个元素void reset();//获取下一个元素E next();//检索当前元素E currentItem();//判断是否还有下一个元素存在boolean hasNext();
}

2.2.2 抽象集合类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:31:11* @description 抽象集合类*/
public interface ListList<E> {//获取迭代器对象的抽象方法(面向接口编程)IteratorIterator<E> Iterator();
}

2.2.3 主题类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:31:52* @description 主题类*/
public class Topic {private String name;public Topic(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

2.2.4 具体迭代类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:32:22* @description 具体迭代类*/
public class TopicIterator implements IteratorIterator<Topic> {//Topic数组private Topic[] topics;//记录存储位置private int position;public TopicIterator(Topic[] topics) {this.topics = topics;position = 0;}@Overridepublic void reset() {position = 0;}@Overridepublic Topic next() {return topics[position++];}@Overridepublic Topic currentItem() {return topics[position];}@Overridepublic boolean hasNext() {if (position >= topics.length) {return false;}return true;}
}

2.2.5 具体集合类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:33:55* @description 具体集合类*/
public class TopicList implements ListList<Topic> {private Topic[] topics;public TopicList(Topic[] topics) {this.topics = topics;}@Overridepublic IteratorIterator<Topic> Iterator() {return new TopicIterator(topics);}
}

2.2.6 测试类

package main.java.cn.test.iterator.V2;/*** @author ningzhaosheng* @date 2024/1/15 15:35:00* @description 测试类*/
public class Test {public static void main(String[] args) {Topic[] topics = new Topic[4];topics[0] = new Topic("topic1");topics[1] = new Topic("topic2");topics[2] = new Topic("topic3");topics[3] = new Topic("topic4");TopicList topicList = new TopicList(topics);IteratorIterator<Topic> iterator = topicList.Iterator();while (iterator.hasNext()) {Topic t = iterator.next();System.out.println(t.getName());}}
}

三、迭代器模式总结

3.1 迭代器模式的优点

  • 迭代器模式支持以不同方式遍历一个集合对象,在同一个集合对象上可以定义多种遍历方式。 在迭代器模式中只需要用一个不同的迭代器来替换原有的迭代器,即可改变遍历算法,也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了集合类。由于引入了迭代器,在原有的集合对象中不需要再自行提供数据遍历等方法,这样可以简化集合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的集合类和迭代器类都很方便,无须修改原有代码,满足 "基于接口编程而非实现" 和 "开闭原则" 的要求。

3.2 迭代器模式的缺点

  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加了类的个数,这在一定程度上增加了系统的复杂性。
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展。

3.3 迭代器模式的使用场景

  • 减少程序中重复的遍历代码。

对于放入一个集合容器中的多个对象来说,访问必然涉及遍历算法。如果我们不将遍历算法封装到容器里(比如,List、Set、Map 等),那么就需要使用容器的人自行去实现遍历算法,这样容易造成很多重复的循环和条件判断语句出现,不利于代码的复用和扩展,同时还会暴露不同容器的内部结构。而使用迭代器模式是将遍历算法作为容器对象自身的一种“属性方法”来使用,能够有效地避免写很多重复的代码,同时又不会暴露内部结构。

  • 当需要为遍历不同的集合结构提供一个统一的接口时或者当访问一个集合对象的内容而无须暴露其内部细节的表示时。

迭代器模式把对不同集合类的访问逻辑抽象出来,这样在不用暴露集合内部结构的情况下,可以隐藏不同集合遍历需要使用的算法,同时还能够对外提供更为简便的访问算法接口。

好了,本次分享就到这里,欢迎大家继续阅读《设计模式》专栏其他设计模式内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!

相关文章:

迭代器模式介绍

目录 一、迭代器模式介绍 1.1 迭代器模式定义 1.2 迭代器模式原理 1.2.1 迭代器模式类图 1.2.2 模式角色说明 1.2.3 示例代码 二、迭代模式的应用 2.1 需求说明 2.2 需求实现 2.2.1 抽象迭代类 2.2.2 抽象集合类 2.2.3 主题类 2.2.4 具体迭代类 2.2.5 具体集合类 …...

算法每日一题: 最大字符串匹配数目 | 哈希 | 哈希表 | 题意分析

hello 大家好&#xff0c;我是星恒 今天给大家带来的是hash&#xff0c;思路有好几种&#xff0c;需要注意的是这中简单的题目需要仔细看条件&#xff0c;往往他们有对应题目的特殊的解法 题目&#xff1a;leetcode 2744给你一个下标从 0 开始的数组 words &#xff0c;数组中包…...

自然语言处理(Natural Language Processing,NLP)解密

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…...

【DevOps-08-5】目标服务器准备脚本,并基于Harbor的最终部署

一、简要描述 告知目标服务器拉取哪个镜像判断当前服务器是否正在运行容器,停止并删除如果目标服务器已经存在当前镜像,删除当前版本的镜像目标服务器拉取Harbor上的镜像将拉取下来的镜像运行成容器二、准备目标服务器脚本文件 1、在部署的目标服务器准备deploy.sh部署脚本 …...

用Java实现01背包问题 用贪心算法

贪心算法不是解决01背包问题的有效方法&#xff0c;因为贪心算法只能保证得到一个近似最优解&#xff0c;而无法保证得到最优解。因此&#xff0c;我们需要使用动态规划来解决01背包问题。以下是使用Java实现的动态规划解法&#xff1a; public class KnapsackProblem {public…...

JUC并发编程-8锁现象

5. 8锁现象 如何判断锁的是谁&#xff01;锁到底锁的是谁&#xff1f; 锁会锁住&#xff1a;对象、Class 深刻理解我们的锁 问题1 两个同步方法&#xff0c;先执行发短信还是打电话 public class dome01 {public static void main(String[] args) {Phone phone new Phon…...

集美大学“第15届蓝桥杯大赛(软件类)“校内选拔赛 D矩阵选数

经典的状态压缩DP int dp[15][(1<<14)10]; int a[15][15]; void solve() {//dp[i][st]考虑到了第i行 并且当前考虑完第i行以后的选择状态是st的所有方案中的最大值for(int i1;i<13;i)for(int j1;j<13;j)cin>>a[i][j];for(int i1;i<13;i){for(int j0;j<…...

Android System Service系统服务--1

因为工作中经常需要解决一些framework层的问题&#xff0c;而framework层功能一般都是system service 的代理stub&#xff0c;然后封装相关接口&#xff0c;并提供给APP层使用&#xff0c;system service则在不同的进程中运行&#xff0c;这样实现了分层&#xff0c;隔离&#…...

【RT-DETR有效改进】华为 | Ghostnetv1一种专为移动端设计的特征提取网络

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…...

45个经典Linux面试题!赶紧收藏!

问题一&#xff1a; 绝对路径用什么符号表示&#xff1f;当前目录、上层目录用什么表示&#xff1f;主目录用什么表示? 切换目录用什么命令&#xff1f; 答案&#xff1a;绝对路径&#xff1a;如/etc/init.d当前目录和上层目录&#xff1a;./ …/主目录&#xff1a;~/切换目…...

将字符串中可能被视为正则表达式的特殊字符进行转义re.escape()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将字符串中可能被视为 正则表达式的特殊字符 进行转义 re.escape() [太阳]选择题 请问以下代码最后输出的结果是&#xff1f; import re s [a-z] print("【显示】s ",s) print(&q…...

C语言:函数指针的使用

在C语言中&#xff0c;函数指针是指向函数的指针变量。它可以存储函数的地址&#xff0c;使得可以通过该指针来调用函数。以下是函数指针的基本概念和用法&#xff1a; 一、基本概念&#xff1a; 声明函数指针&#xff1a; returnType (*pointerName)(parameterTypes); 这里 r…...

「实战应用」如何用DHTMLX Gantt构建类似JIRA式的项目路线图(二)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 在web项目中使用DHTMLX Gantt时&#xff0c;开发人员经常需要满足与UI外观相关的各种需求。因此他们必须确定JavaScript甘特图库的…...

Webpack5入门到原理18:Plugin 原理

Plugin 的作用 通过插件我们可以扩展 webpack&#xff0c;加入自定义的构建行为&#xff0c;使 webpack 可以执行更广泛的任务&#xff0c;拥有更强的构建能力。 Plugin 工作原理 webpack 就像一条生产线&#xff0c;要经过一系列处理流程后才能将源文件转换成输出结果。 这条…...

PWM之舵机

舵机又称直流电机&#xff0c;如下图 本节承接上节&#xff0c;具体的PWM技术已经在上一节讲的很详细了&#xff0c;本节就不再讲了&#xff0c;那么我们的重点就放在直流电机的工作原理上了。 一、工作原理 我们研究直流电机&#xff0c;主要式研究直流电机旋转速度的调节&a…...

Python并发与多线程:IO并发(阻塞IO、非阻塞IO、IO多路复用、异步IO)

在Python中&#xff0c;有多种处理并发的方式&#xff0c;其中之一就是使用多线程进行IO并发操作。在IO操作中&#xff0c;有四种常见的方式&#xff1a;阻塞IO、非阻塞IO、IO多路复用和异步IO。 阻塞IO&#xff08;Blocking IO&#xff09;&#xff1a;当执行一个IO操作时&…...

React16源码: React中的IndeterminateComponent的源码实现

IndeterminateComponent 1 &#xff09;概述 这是一个比较特殊的component的类型&#xff0c; 就是还没有被指定类型的component在一个fibrer被创建的时候&#xff0c;它的tag可能会是 IndeterminateComponent在 packages/react-reconciler/src/ReactFiber.js 中&#xff0c;有…...

SpringBoot:详解Bean生命周期和作用域

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、生命周期二…...

【图解数据结构】顺序表实战指南:手把手教你详细实现(超详细解析)

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;图解数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️线性表1.1 &#x1f514;线性表的定义1.2 &#x1f514;线性表的存储结构 二. ⛳️顺序表…...

WordPress怎么禁用文章和页面古腾堡块编辑器?如何恢复经典小工具?

现在下载WordPress最新版来搭建网站&#xff0c;默认的文章和页面编辑器&#xff0c;以及小工具都是使用古腾堡编辑器&#xff08;Gutenberg块编辑器&#xff09;。虽然有很多站长说这个编辑器很好用&#xff0c;但是仍然有很多站长用不习惯&#xff0c;觉得操作太难了&#xf…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...