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

【设计模式】【行为型模式】迭代器模式(Iterator)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中… 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
🎵 当你的天空突然下了大雨,那是我在为你炸乌云

文章目录

  • 一、入门
    • 什么是迭代器模式?
    • 为什么要迭代器模式?
    • 怎么实现迭代器模式?
  • 二、迭代器模式在源码中的运用
    • Java 集合框架(Java Collections Framework)
      • Java集合框架迭代器的使用
      • Java集合框架迭代器的源码实现
  • 三、总结
    • 迭代器模式的优点
    • 迭代器模式的缺点
    • 迭代器模式的典型应用场景

一、入门

什么是迭代器模式?

迭代器模式(Iterator Pattern)是一种行为设计模式,它提供了一种顺序访问聚合对象中元素的方法,而不需要暴露其底层表示。迭代器模式将遍历逻辑从聚合对象中分离出来,使得聚合对象可以专注于数据存储,而迭代器负责遍历。

为什么要迭代器模式?

在没有迭代器模式的情况下,客户端代码需要直接依赖书架的内部结构(如数组或列表)来遍历书籍。这种方式会导致遍历逻辑与书架类耦合。

// 书籍类
class Book {private String name;public Book(String name) {this.name = name;}public String getName() {return name;}
}// 书架类
class BookShelf {private Book[] books;private int size;public BookShelf(int capacity) {books = new Book[capacity];size = 0;}public void addBook(Book book) {if (size < books.length) {books[size++] = book;}}// 暴露内部数组public Book[] getBooks() {return books;}// 暴露书架大小public int getSize() {return size;}
}// 客户端代码
public class LibraryWithoutIterator {public static void main(String[] args) {BookShelf bookShelf = new BookShelf(3);bookShelf.addBook(new Book("Design Patterns"));bookShelf.addBook(new Book("Clean Code"));bookShelf.addBook(new Book("Refactoring"));// 直接依赖书架的内部结构(数组)进行遍历Book[] books = bookShelf.getBooks();for (int i = 0; i < bookShelf.getSize(); i++) {System.out.println(books[i].getName());}}
}

存在的问题

  1. 耦合性强:客户端代码直接依赖书架的内部结构(数组),如果书架的存储结构改为链表,客户端代码也需要修改。
  2. 破坏封装性:书架类暴露了内部数据(数组和大小),客户端代码可以直接操作这些数据,可能导致数据不一致。
  3. 无法统一遍历接口:如果图书馆中有多种存储结构(如书架、电子书库等),客户端代码需要为每种结构编写特定的遍历逻辑。

怎么实现迭代器模式?

迭代器模式的组成

  1. 迭代器接口(Iterator Interface):定义了遍历元素所需的操作,如next()hasNext()等。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,负责管理当前遍历的位置。
  3. 聚合接口(Aggregate Interface):定义了创建迭代器的方法,如createIterator()
  4. 具体聚合类(Concrete Aggregate):实现聚合接口,返回一个具体迭代器的实例。

【案例】图书管理 - 改
在这里插入图片描述
迭代器接口(Iterator Interface)Iterator迭代器接口,定义遍历聚合对象所需的方法。

interface Iterator<T> {boolean hasNext();T next();
}
具体迭代器(Concrete Iterator):BookShelfIterator 类,实现迭代器接口,负责管理当前遍历的位置,并实现具体的遍历逻辑。
// 具体迭代器
class BookShelfIterator implements Iterator<Book> {private BookShelf bookShelf; // 关联的具体聚合类private int currentIndex = 0; // 当前遍历的位置// 构造函数,传入具体聚合类public BookShelfIterator(BookShelf bookShelf) {this.bookShelf = bookShelf;}@Overridepublic boolean hasNext() {return currentIndex < bookShelf.getSize(); // 判断是否还有下一个元素}@Overridepublic Book next() {Book book = bookShelf.getBookAt(currentIndex); // 获取当前元素currentIndex++; // 移动游标return book;}
}

聚合接口(Aggregate Interface): Aggregate接口,定义创建迭代器的方法。

// 聚合接口
interface Aggregate<T> {Iterator<T> createIterator(); // 创建迭代器
}
具体聚合类(Concrete Aggregate):BookShelf类,实现聚合接口,负责存储和管理数据,并提供创建迭代器的方法。
// 具体聚合类
class BookShelf implements Aggregate<Book> {private Book[] books; // 存储书籍的数组private int size;      // 当前书籍数量// 构造函数,初始化书架容量public BookShelf(int capacity) {books = new Book[capacity];size = 0;}// 添加书籍public void addBook(Book book) {if (size < books.length) {books[size++] = book;}}// 获取指定位置的书籍public Book getBookAt(int index) {return books[index];}// 获取当前书籍数量public int getSize() {return size;}// 实现聚合接口,创建迭代器@Overridepublic Iterator<Book> createIterator() {return new BookShelfIterator(this); // 将当前书架对象传递给迭代器}
}

Book类

class Book {private String name;public Book(String name) {this.name = name;}public String getName() {return name;}
}

测试类

// 客户端代码
public class LibraryDemo {public static void main(String[] args) {// 创建一个书架BookShelf bookShelf = new BookShelf(3);bookShelf.addBook(new Book("Design Patterns"));bookShelf.addBook(new Book("Clean Code"));bookShelf.addBook(new Book("Refactoring"));// 创建迭代器Iterator<Book> iterator = bookShelf.createIterator();// 使用迭代器遍历书架System.out.println("Books in BookShelf:");while (iterator.hasNext()) {Book book = iterator.next();System.out.println(book.getName());}}
}

输出结果

Books in BookShelf:
Design Patterns
Clean Code
Refactoring

二、迭代器模式在源码中的运用

Java 集合框架(Java Collections Framework)

Java集合框架迭代器的使用

Java 的集合框架(如 ArrayListLinkedListHashSet 等)广泛使用了迭代器模式。每个集合类都实现了 Iterable 接口,并提供了 iterator() 方法来返回一个迭代器。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class JavaCollectionExample {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Apple");list.add("Banana");list.add("Cherry");// 使用迭代器遍历集合Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

Java集合框架迭代器的源码实现

Iterable接口:定义了iterator()方法,用于返回一个迭代器。

public interface Iterable<T> {Iterator<T> iterator();
}

Iterator接口:定义了遍历集合的方法,如hasNext()next()

public interface Iterator<E> {boolean hasNext();E next();void remove(); // 可选操作
}

ArrayList中的迭代器实现:

public Iterator<E> iterator() {return new Itr();
}private class Itr implements Iterator<E> {int cursor;       // 当前遍历的位置int lastRet = -1; // 上一次返回的元素索引public boolean hasNext() {return cursor != size;}public E next() {// 返回当前元素,并移动游标// ...}public void remove() {// 删除上一次返回的元素// ...}
}

三、总结

迭代器模式的优点

  1. 解耦遍历逻辑与聚合对象
    • 将遍历逻辑从聚合对象中分离出来,聚合对象可以专注于数据存储,而迭代器负责遍历。
    • 符合单一职责原则。
  2. 统一遍历接口
    • 提供了一种统一的方式来遍历不同类型的聚合对象(如数组、链表、树等)。
    • 客户端代码无需关心聚合对象的内部结构。
  3. 支持多种遍历方式
    • 可以为同一个聚合对象定义多个迭代器,实现不同的遍历方式(如正序遍历、逆序遍历、深度优先遍历等)。
  4. 增强封装性
    • 隐藏了聚合对象的内部结构,客户端代码只能通过迭代器访问元素,无法直接操作聚合对象的内部数据。
  5. 开闭原则
    • 新增聚合类和迭代器类不会影响现有代码,易于扩展。

迭代器模式的缺点

  1. 增加复杂性
    • 对于简单的聚合对象,使用迭代器模式可能会增加代码复杂性。
    • 如果遍历逻辑非常简单,直接使用 for 循环可能更直观。
  2. 性能开销
    • 迭代器模式可能会引入额外的性能开销,尤其是在遍历大型数据集时。
  3. 不适合频繁修改的聚合对象
    • 如果聚合对象在遍历过程中频繁修改(如添加或删除元素),可能会导致迭代器失效或抛出异常。

迭代器模式的典型应用场景

  1. 集合框架
    • Java 的集合框架(如 ArrayList、LinkedList、HashSet 等)广泛使用了迭代器模式。
  2. 文件系统遍历
    • 遍历文件系统中的目录和文件时,可以使用迭代器模式封装遍历逻辑。
  3. 数据库查询结果遍历
    • 遍历数据库查询结果集时,可以使用迭代器模式提供统一的遍历接口。
  4. 树形结构遍历
    • 遍历树形结构(如 DOM 树、组织结构树等)时,可以使用迭代器模式支持多种遍历方式(如深度优先遍历、广度优先遍历等)。

相关文章:

【设计模式】【行为型模式】迭代器模式(Iterator)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…...

二次封装axios解决异步通信痛点

为了方便扩展,和增加配置的灵活性,这里将通过封装一个类来实现axios的二次封装,要实现的功能包括: 为请求传入自定义的配置,控制单次请求的不同行为在响应拦截器中对业务逻辑进行处理,根据业务约定的成功数据结构,返回业务数据对响应错误进行处理,配置显示对话框或消息形…...

mac 意外退出移动硬盘后再次插入移动硬盘不显示怎么办

第一步&#xff1a;sudo ps aux | grep fsck 打开mac控制台输入如下指令&#xff0c;我们看到会出现两个进程&#xff0c;看进程是root的这个 sudo ps aux|grep fsck 第二步&#xff1a;杀死进程 在第一步基础上我们知道不显示u盘的进程是&#xff1a;62319&#xff0c;我们…...

如何下载AndroidStudio的依赖的 jar,arr文件到本地

一、通过jitpack.io 下载依赖库 若需要下载 com.github.xxxxx:yy-zzz:0.0.2 的 jar则 https://jitpack.io/com/github/xxxxx/yy-zzz/0.0.2/ 下会列出如下build.logyy-zzz-0.0.2.jaryy-zzz-0.0.2.pomyy-zzz-0.0.2.pom.md5yy-zzz-0.0.2.pom.sha1jar 的下载路径为https://jitpack…...

FFmpeg Video options

FFmpeg视频相关选项 1. -vframes number (output) 设置输出视频帧数 示例&#xff1a; ffmpeg -i input.mp4 -vframes 90 output.mp4 表示输出90帧视频 2. -r[:stream_specifier] fps (input/output,per-stream) 设置帧率(rate) 示例&#xff1a; ffmpeg -i input.mp4…...

CEF132编译指南 MacOS 篇 - 构建 CEF (六)

1. 引言 经过前面一系列的精心准备&#xff0c;我们已经完成了所有必要的环境配置和源码获取工作。本篇作为 CEF132 编译指南系列的第六篇&#xff0c;将详细介绍如何在 macOS 系统上构建 CEF132。通过配置正确的编译命令和参数&#xff0c;我们将完成 CEF 的构建工作&#xf…...

Python大数据可视化:基于python的电影天堂数据可视化_django+hive

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 电影数据 看板展示 我的信息 摘要 电影天堂数据可视化是…...

LLM之循环神经网络(RNN)

在人工智能的领域中&#xff0c;神经网络是推动技术发展的核心力量。今天&#xff0c;让我们深入探讨循环神经网络&#xff08;RNN&#xff09; 一、神经网络基础 &#xff08;1&#xff09;什么是神经网络 神经网络&#xff0c;又称人工神经网络&#xff0c;其设计灵感源于人…...

YOLOv5 目标检测优化:降低误检与漏检

1. 引言 在目标检测任务中&#xff0c;误检&#xff08;False Positive, FP&#xff09;和漏检&#xff08;False Negative, FN&#xff09;是影响检测性能的两个主要问题。误检意味着模型检测到了不存在的目标&#xff0c;而漏检则指模型未能检测到真实存在的目标。本文将介绍…...

在nodejs中使用RabbitMQ(七)实现生产者确认

生产者&#xff1a;批量发送消息&#xff08;每批10条&#xff09;&#xff0c;每条消息附带唯一 correlationId&#xff0c;并监听确认队列&#xff08;ackQueue&#xff09;。 消费者&#xff1a;处理消息后&#xff0c;通过 ackQueue 返回确认消息&#xff08;携带原 corre…...

vue中Img图片资源require导入时数据没有过来的时候报错了-解决方案

src_views_followOrder_myFollow_index_vue.js:903 Uncaught (in promise) Error: Cannot find module ./undefined-icon.svg 该错误表示在Vue组件或JavaScript文件中找不到名为“undefined-icon.svg”的模块。可能原因是: 1. 路径错误:检查文件路径是否正确,确保文件实际上…...

Java:204 基于springboot零食销售商城的设计与实现

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统主要分为管理员和用户、商家。 用户可以使用网站首页的登录注册界面进行在线登录注册&#xff0c;并且注册登录后方可使用系统的各种功能以及购物…...

harmonyOS的文件的增、删、读、写相关操作(fs/content)

注意: 操作harmonyOS的文件只能对app沙箱内的文件进行操作 牵扯到两个支持点: fs和content这两个API; 具体的操作方法看下图: 创建文件 //js 引入 import fs from "ohos.files.fs" import featureAbility from "ohos.ability.featureAbility"; // 上下…...

【golang】量化开发学习(一)

均值回归策略简介 均值回归&#xff08;Mean Reversion&#xff09;假设价格会围绕均值波动&#xff0c;当价格偏离均值一定程度后&#xff0c;会回归到均值。 基本逻辑&#xff1a; 计算一段时间内的移动均值&#xff08;如 20 天均线&#xff09;。当当前价格高于均值一定比…...

4090单卡挑战DeepSeek r1 671b:尝试量化后的心得的分享

引言&#xff1a; 最近&#xff0c;DeepSeek-R1在完全开源的背景下&#xff0c;与OpenAI的O1推理模型展开了激烈竞争&#xff0c;引发了广泛关注。为了让更多本地用户能够运行DeepSeek&#xff0c;我们成功将R1 671B参数模型从720GB压缩至131GB&#xff0c;减少了80%&#xff…...

MySQL数据库(八)☞ 我是不是锁神

目录 1 全局锁的应用 2 索引对行锁的影响 3 表锁&#xff08;显式&#xff09;--表级锁 4 元数据锁 MDL(隐式)--表级锁 5 意向锁(Intention)--IS锁 IX锁--表级锁&#xff08;隐式&#xff09; 6 记录锁-(Record)-S锁 X锁 -- 行级锁 7 如何理解select ... lock in share …...

AI法理学与责任归属:技术演进下的法律重构与伦理挑战

文章目录 引言:智能时代的新型法律困境一、AI技术特性对传统法理的冲击1.1 算法黑箱与可解释性悖论1.2 动态学习系统的责任漂移1.3 多智能体协作的责任稀释二、AI法理学的核心争议点2.1 法律主体资格认定2.2 因果关系的技术解构2.3 过错标准的重新定义三、责任归属的实践案例分…...

华象新闻 | 2月20日前谨慎升级 PostgreSQL 版本

各位 PostgreSQL 用户&#xff0c;建议近期进行升级 PostgreSQL 版本。 2月20日计划进行非周期性版本发布 PostgreSQL全球开发团队计划于2025年2月20日进行一次非周期性发布&#xff0c;以解决2025年2月13日更新版本中引入的一个回归问题。 2月13日的更新版本包括了17.3、16.7、…...

【NLP】循环神经网络RNN

目录 一、认识RNN 二、RNN模型分类 三、传统RNN模型 3.1 结构分析 3.2 Pytorch构建RNN模型 3.3 优缺点 一、认识RNN RNN(Recurrent Neural Network)&#xff0c;中文称作循环神经网络&#xff0c;一般以序列数据为输入&#xff0c;通过网络内部的结构设计有效捕捉序列之…...

pnpm, eslint, vue-router4, element-plus, pinia

利用 pnpm 创建 vue3 项目 pnpm 包管理器 - 创建项目 Eslint 配置代码风格(Eslint用于规范纠错&#xff0c;prettier用于美观&#xff09; 在 设置 中配置保存时自动修复 提交前做代码检查 husky是一个 git hooks工具&#xff08;git的钩子工具&#xff0c;可以在特定实际执行特…...

Vue的简单入门 一

声明&#xff1a;本版块根据B站学习&#xff0c;创建的是vue3项目&#xff0c;用的是vue2语法风格&#xff0c;仅供初学者学习。 目录 一、Vue项目的创建 1.已安装15.0或更高版本的Node.js 2.创建项目 二、 简单认识目录结构 三、模块语法中的指令 1.v-html 1.文本插值…...

VMware Workstate 的 Ubuntu18 安装 vmware tools(不安装没法共享)

在共享主机路径后&#xff0c;可以在&#xff1a; /mnt/hgfs/下方找到共享的文件。但没有安装vmware tool时是没法共享的。 如何安装vmware tool&#xff0c;网上版本很多。这里记录一下&#xff1a; VMware Workstation 17 Pro&#xff0c;版本&#xff1a;17.6.0 虚拟机系统…...

深入Flask:如何优雅地处理HTTP请求与响应

哈喽,大家好,我是木头左! 本文将带你深入了解如何在Flask中优雅地处理HTTP请求和响应,让你的应用更加高效、安全和用户友好。 创建一个简单的Flask应用 让从创建一个最简单的Flask应用开始: from flask import Flaskapp = Flask(__name__)@app.route(/) def...

Typescript 【详解】配置文件 tsconfig.json

用于控制 TypeScript 编译器如何将 .ts 文件编译为 .js 文件 可以使用命令生成 npx tsc --init{"compilerOptions": {"target": "ES6","module": "commonjs","strict": true},"include": ["src/…...

GC 基础入门

什么是GC&#xff08;Garbage Collection&#xff09;&#xff1f; 内存管理方式通常分为两种&#xff1a; 手动内存管理&#xff08;Manual Memory Management&#xff09;自动内存管理&#xff08;Garbage Collection, GC&#xff09; 手动内存管理 手动内存管理是指开发…...

坑多多之AC8257 i2c1 rtc-pcf8563

pcf85163 ordering information Ordering information Package Description Version Marking code PCF85163T/1 SO8 ① SOT96-1 PF85163 PCF85163TS/1 TSSOP8 ② SOT505-1 85163 ①plastic small outline package; 8 leads;body width 3.9 mm ②plastic thin…...

UE求职Demo开发日志#32 优化#1 交互逻辑实现接口、提取Bag和Warehouse的父类

1 定义并实现交互接口 接口定义&#xff1a; // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "UObject/Interface.h" #include "MyInterActInterface.generated.h…...

自动化测试题

1.什么项目适合做自动化测试&#xff1f; 答&#xff1a;一般来说&#xff0c;适合做自动化测试的项目应该满足以下几个条件&#xff1a; 项目需求稳定&#xff0c;变更不频繁。 项目周期较长&#xff0c;需要反复进行回归测试。 项目功能较复杂&#xff0c;涉及多个模块和…...

vite配置proxy和nginx同步配置反向代理,vite的base含义

vite配置代理是为了在开发环境下联调服务器接口&#xff0c;如果不配置代理&#xff0c;开发时会出现跨域&#xff0c; 会在请求的url的前缀添加标识如/api,代理请求时在rewrite为""&#xff0c;或者rewrite为其他字符串&#xff0c; 项目打包部署后&#xff0c;需要…...

如何在 Mac 上解决 Qt Creator 安装后应用程序无法找到的问题

在安装Qt时&#xff0c;遇到了一些问题&#xff0c;尤其是在Mac上安装Qt后&#xff0c;发现Qt Creator没有出现在应用程序中。通过一些搜索和操作&#xff0c;最终解决了问题。以下是详细的记录和解决方法。 1. 安装Qt后未显示Qt Creator 安装完成Qt后&#xff0c;启动应用程…...