【设计模式】【行为型模式】迭代器模式(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;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < bookShelf.getSize(); // 判断是否还有下一个元素
    }

    @Override
    public 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;
    }

    // 实现聚合接口,创建迭代器
    @Override
    public 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 树、组织结构树等)时,可以使用迭代器模式支持多种遍历方式(如深度优先遍历、广度优先遍历等)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

论文解读之DeepSeek R1

今天带来DeepSeek R1的解读 一、介绍 deepseek主打复杂推理任务&#xff0c;如数学、代码任务。 R1以预训练过的V1-base初始化&#xff0c;主要发挥了RL在长思维链上的优势&#xff0c;R1-Zero直接RL而在前置步骤中不进行SFT&#xff0c;即缺少了有监督的指令微调阶段&#…

Linux:用 clang 编译带 sched_ext 功能内核

文章目录 1. 前言2. 编译过程2.1 准备内核源代码2.2 安装编译工具2.3 配置、编译、运行2.3.1 配置2.3.2 编译2.3.3 运行 3. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 编译过程 …

FPGA之​​​​​​​​​​​​​​HRBANK与HOBANK有什么区别?

在FPGA设计中&#xff0c;HP Bank&#xff08;High-Performance Bank&#xff09;与HR Bank&#xff08;High-Range Bank&#xff09;是针对I/O电气特性划分的不同区域&#xff0c;二者的主要区别在于支持的电压范围、信号速率以及应用场景。以下是具体对比&#xff1a; 核心区…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_ssl_init 函数

#if (NGX_OPENSSL)ngx_ssl_init(log); #endif objs/ngx_auto_config.h 中 #ifndef NGX_OPENSSL #define NGX_OPENSSL 1 #endif 所以这个条件编译成立 NGX_OPENSSL 是一个宏定义&#xff0c;用于控制与 OpenSSL 相关的功能是否被启用 若用户通过./configure参数&#xff08;如-…

pandas(13 Caveats Gotchas和SQL比较)

前面内容&#xff1a;pandas(12 IO工具和稀松数据) 目录 一、Caveats警告 & Gotchas预见 1.1 在Pandas中使用if/Truth语句 1.2 位运算布尔 1.3 isin操作 1.4 重新索引reindex和 loc&iloc 使用注意事项 1.5 loc和iloc 二、Python Pandas 与SQL的比较 2.1 数…

MongoDB 7 分片副本集升级方案详解(下)

#作者&#xff1a;任少近 文章目录 1.4 分片升级1.5 升级shard11.6 升级shard2,shard31.7 升级mongos1.8重新启用负载均衡器1.9 推荐MongoDB Compass来验证数据 2 注意事项&#xff1a; 1.4 分片升级 使用“滚动”升级从 MongoDB 7.0 升级到 8.0&#xff0c;即在其他成员可用…

洛谷 P2894 USACO08FEB Hotel 题解

题意 第一行输入 n , m n,m n,m&#xff0c; n n n 代表有 n n n 个房间 ( 1 ≤ n ≤ 50 , 000 ) (1\leq n \leq 50,000) (1≤n≤50,000)&#xff0c;编号为 1 ∼ n 1 \sim n 1∼n&#xff0c;开始都为空房&#xff0c; m m m 表示以下有 m m m 行操作 ( 1 ≤ m < 50…

VS2022中.Net Api + Vue 从创建到发布到IIS

VS2022中.Net Api Vue 从创建到发布到IIS 前言一、先决条件二、创建项目三、运行项目四、增加API五、发布到IIS六、设置Vue的发布 前言 最近从VS2019 升级到了VS2022,终于可以使用官方的.Net Vue 组合了,但是使用过程中还是有很多问题,这里记录一下. 一、先决条件 Visual …

BGP分解实验·18——BGP选路原则之权重

在本地对进入的NLRI做权重设置&#xff0c;从而对过滤特定的路由进行优选。严格来说&#xff0c;权重值并不能算是路径属性&#xff0c;因为它并处传递&#xff0c;所能影响的仅仅限于本地路由器。 实验拓扑如下&#xff1a; 完成实验拓扑的基础实验&#xff0c;R1的配置如下…

正点原子ESP32S3系列开发板全面支持小智AI

什么是小智AI? 小智AI项目是由虾哥发起并开源的一个项目。该项目能帮助更多人入门AI硬件开发&#xff0c;了解如何将当下飞速发展的大语言模型应用到实际的硬件设备中。 小智AI功能如下&#xff1a; WiFi / ML307 Cat.1 4G BOOT键唤醒和打断&#xff0c;支持点击和长按两种触…

【2025最新计算机毕业设计】基于SpringBoot+Vue高校社团管理系统 【提供源码+答辩PPT+文档+项目部署】

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

探寻性能优化:如何衡量?如何决策?

目录 一、衡量指标说明 &#xff08;一&#xff09;响应时间&#xff08;Response Time&#xff09; 平均响应时间&#xff08;Average Response Time&#xff09; 百分位数响应时间&#xff08;Percentile Response Time&#xff09; &#xff08;二&#xff09;吞吐量&a…

YOLO11环境搭建CUDA12.6

1.安装CUDA和cuDNN 1.1安装CUDA 1.1.1查看当前你的电脑显卡支持的最高CUDA版本,后面的安装不能超过它 通过命令的方式查看 输入nvidia-smi 1.1.2 下载CUDA 官网地址:CUDA Toolkit Archive | NVIDIA Developer 选择cuda_12.6.3 下载完成后,如下: 安装,一直下一步即可:…

Java多线程——性能与可伸缩性

可伸缩性 当增加计算资源时&#xff08;如CPU、内存、存储容量或I/O带宽&#xff09;&#xff0c;程序的吞吐量或处理能力能相应的增加 Amdahl定理 F为必须被串行执行的部分&#xff0c;在N个处理器的机器中&#xff0c;在增加计算资源所能达到的最高加速比是 N趋于无穷大时…

Spring Boot 项目启动报错 “找不到或无法加载主类” 解决笔记

一、问题描述 在使用 IntelliJ IDEA 开发基于 Spring Boot 框架的 Java 程序时&#xff0c;原本项目能够正常启动。但在后续编写代码并重建项目后&#xff0c;再次尝试运行却出现了 “错误&#xff1a;找不到或无法加载主类 com.example.springboot.SpringbootApplication” 的…

snort3.0-ubuntu18.04 64入侵检测安装与使用

在日常生活中&#xff0c;很多人怀疑自己的手机、电脑被监控了&#xff0c;担心自己的隐私泄漏&#xff0c;实际上最佳的检测方式就是终端检测&#xff0c;也就是EDR&#xff0c;但是就是有那么多的人在网上大放厥词&#xff0c;说任何EDR杀毒软件都检测不到监控&#xff0c;毕…

Spring Cloud-Sentinel

Sentinel服务熔断与限流 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。 官网地址&#xff1a;home | Sentinelhttps://sen…

蓝桥与力扣刷题(230 二叉搜索树中第k小的元素)

题目&#xff1a;给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 小的元素&#xff08;从 1 开始计数&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff1a;1示例 2&#xff…

安卓设备调试h5页面(调试)

1、在chrome浏览器中输入网址&#xff1a;chrome://inspect/#devices 2、设备连接usb&#xff0c;打开对应app 3、点击inspect fallback&#xff0c;打开对应调试页面

第1章大型互联网公司的基础架构——1.6 RPC服务

你可能在1.1节的引言中注意到业务服务层包括HTTP服务和RPC服务&#xff0c;两者的定位不一样。一般来说&#xff0c;一个业务场景的核心逻辑都是在RPC服务中实现的&#xff0c;强调的是服务于后台系统内部&#xff0c;所谓的“微服务”主要指的就是RPC服务&#xff1b;而HTTP服…