迭代器模式:统一数据遍历方式的设计模式

news2025/7/15 16:37:54

迭代器模式:统一数据遍历方式的设计模式

一、模式核心:将数据遍历逻辑与数据结构解耦

在软件开发中,不同的数据结构(如数组、链表、集合)有不同的遍历方式。如果客户端直接依赖这些数据结构的内部实现来遍历元素,会导致代码耦合度高且难以维护。

迭代器模式(Iterator Pattern) 提供了一种统一的方式来遍历不同的数据结构,而无需暴露数据结构的内部表示。其核心解决:

  • 解耦遍历逻辑:将遍历逻辑从数据结构中分离,客户端通过迭代器统一操作。
  • 支持多种遍历方式:可以为同一数据结构提供不同的遍历策略(如正向遍历、反向遍历)。
  • 简化客户端代码:客户端无需关心数据结构的具体类型,只需通过迭代器接口遍历元素。

核心思想与 UML 类图

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

  1. 抽象迭代器(Iterator):定义遍历元素的接口(如 hasNext()next())。
  2. 具体迭代器(Concrete Iterator):实现抽象迭代器接口,负责具体的数据遍历。
  3. 抽象聚合(Aggregate):定义创建迭代器的接口(如 createIterator())。
  4. 具体聚合(Concrete Aggregate):实现抽象聚合接口,返回具体迭代器。

PlantUML Diagram

二、核心实现:数组集合的迭代器

1. 定义抽象迭代器接口

public interface Iterator {  
    boolean hasNext(); // 是否有下一个元素  
    Object next(); // 获取下一个元素  
}  

2. 定义抽象聚合接口

public interface Aggregate {  
    Iterator createIterator(); // 创建迭代器  
}  

3. 实现具体聚合类(数组集合)

public class ConcreteAggregate implements Aggregate {  
    private Object[] items;  
    private int size;  

    public ConcreteAggregate(int capacity) {  
        items = new Object[capacity];  
        size = 0;  
    }  

    public void add(Object item) {  
        if (size < items.length) {  
            items[size++] = item;  
        }  
    }  

    @Override  
    public Iterator createIterator() {  
        return new ConcreteIterator(this); // 返回具体迭代器  
    }  

    // 获取集合长度(供迭代器使用)  
    public int getSize() {  
        return size;  
    }  

    // 获取指定索引的元素(供迭代器使用)  
    public Object getItem(int index) {  
        return items[index];  
    }  
}  

4. 实现具体迭代器类

public class ConcreteIterator implements Iterator {  
    private ConcreteAggregate aggregate;  
    private int index; // 当前遍历位置  

    public ConcreteIterator(ConcreteAggregate aggregate) {  
        this.aggregate = aggregate;  
        index = 0;  
    }  

    @Override  
    public boolean hasNext() {  
        return index < aggregate.getSize(); // 未遍历到末尾  
    }  

    @Override  
    public Object next() {  
        if (hasNext()) {  
            return aggregate.getItem(index++); // 返回当前元素并后移索引  
        }  
        return null;  
    }  
}  

5. 客户端使用迭代器

public class ClientDemo {  
    public static void main(String[] args) {  
        // 创建聚合对象并添加元素  
        ConcreteAggregate aggregate = new ConcreteAggregate(3);  
        aggregate.add("Apple");  
        aggregate.add("Banana");  
        aggregate.add("Cherry");  

        // 获取迭代器并遍历元素  
        Iterator iterator = aggregate.createIterator();  
        while (iterator.hasNext()) {  
            System.out.println(iterator.next());  
        }  
    }  
}  

输出结果

Apple  
Banana  
Cherry  

三、进阶:支持反向遍历的迭代器

通过扩展具体迭代器,可以为同一聚合提供不同的遍历策略(如反向遍历)。

1. 新增反向迭代器类

public class ReverseIterator implements Iterator {  
    private ConcreteAggregate aggregate;  
    private int index; // 当前遍历位置(从末尾开始)  

    public ReverseIterator(ConcreteAggregate aggregate) {  
        this.aggregate = aggregate;  
        index = aggregate.getSize() - 1; // 初始位置为最后一个元素  
    }  

    @Override  
    public boolean hasNext() {  
        return index >= 0; // 未遍历到开头  
    }  

    @Override  
    public Object next() {  
        if (hasNext()) {  
            return aggregate.getItem(index--); // 返回当前元素并前移索引  
        }  
        return null;  
    }  
}  

2. 修改聚合类以支持多种迭代器

public class ConcreteAggregate {  
    // ... 原有代码 ...  

    // 新增创建反向迭代器的方法  
    public Iterator createReverseIterator() {  
        return new ReverseIterator(this);  
    }  
}  

3. 客户端使用反向迭代器

public class ClientDemo {  
    public static void main(String[] args) {  
        // ... 创建聚合对象 ...  

        // 反向遍历  
        Iterator reverseIterator = aggregate.createReverseIterator();  
        while (reverseIterator.hasNext()) {  
            System.out.println(reverseIterator.next());  
        }  
    }  
}  

输出结果

Cherry  
Banana  
Apple  

四、框架与源码中的迭代器实践

1. Java 集合框架(Iterator 接口)

Java 的 java.util.Iterator 是迭代器模式的标准实现,所有集合类(如 ArrayListHashSet)均实现了 Iterable 接口(包含 iterator() 方法)。

List<String> list = new ArrayList<>();  
list.add("A");  
list.add("B");  
Iterator<String> it = list.iterator();  
while (it.hasNext()) {  
    System.out.println(it.next());  
}  

2. MyBatis 结果集遍历

MyBatis 在处理查询结果时,通过 ResultHandler 接口实现类似迭代器的功能,将结果集逐行处理,避免一次性加载大量数据到内存。

sqlSession.select("selectUserList", new ResultHandler<User>() {  
    @Override  
    public void handleResult(ResultContext<User> context) {  
        User user = context.getResultObject();  
        processUser(user); // 逐行处理结果  
    }  
});  

五、避坑指南:正确使用迭代器模式的 3 个要点

1. 确保迭代器的独立性

每个迭代器应独立维护遍历状态,避免多个迭代器共享状态导致数据不一致。

2. 处理并发修改异常

在迭代过程中修改聚合对象(如新增 / 删除元素)可能导致 ConcurrentModificationException,需通过 fail-fast 机制或复制集合数据处理。

3. 避免过度设计

对于简单的数据结构(如数组),直接使用索引遍历可能更高效,无需强行引入迭代器模式。

六、总结:何时该用迭代器模式?

适用场景核心特征典型案例
数据结构复杂数据结构内部实现复杂,需隐藏遍历细节链表、树状结构遍历
多遍历策略需要为同一数据结构提供多种遍历方式正向 / 反向遍历、深度 / 广度优先
解耦客户端与数据结构客户端不依赖数据结构的具体实现集合框架、ORM 结果集处理

迭代器模式通过分离数据遍历逻辑,提升了代码的可维护性和扩展性。下一篇我们将探讨观察者模式,解析如何实现对象间的消息订阅与发布,敬请期待!

扩展思考:迭代器模式 vs 枚举(Enumeration)

类型功能差异线程安全遍历控制
迭代器支持元素删除(remove()非线程安全主动控制遍历
枚举(旧版)仅支持遍历,不支持删除非线程安全被动遍历

在 Java 中,迭代器已全面替代枚举,成为集合遍历的标准方式。

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

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

相关文章

LeetCode每日一题4.23

题目 问题分析 计算每个数字的数位和&#xff1a;对于从 1 到 n 的每个整数&#xff0c;计算其十进制表示下的数位和。 分组&#xff1a;将数位和相等的数字放到同一个组中。 统计每个组的数字数目&#xff1a;统计每个组中有多少个数字。 找到并列最多的组&#xff1a;返回数…

RunnerGo API性能测试实战与高并发调优

API 性能测试通过模拟不同负载场景&#xff0c;量化评估 API 的响应时间、吞吐量、稳定性、可扩展性等性能指标&#xff0c;关注其在正常、高峰甚至极限负载下的表现。这有助于确保 API 稳定高效地运行&#xff0c;为调用者提供优质服务。 接下来&#xff0c;我们借助 RunnerG…

STM32——相关软件安装

本文是根据江协科技提供的教学视频所写&#xff0c;旨在便于日后复习&#xff0c;同时供学习嵌入式的朋友们参考&#xff0c;文中涉及到的所有资料也均来源于江协科技&#xff08;资料下载&#xff09;。 Keil5 MDK安装 1.安装Keil5 MDK2.安装器件支持包方法一&#xff1a;离线…

数据结构入门【算法复杂度】超详解深度解析

&#x1f31f; 复杂度分析的底层逻辑 复杂度是算法的"DNA"&#xff0c;它揭示了两个核心问题&#xff1a; 数据规模(n)增长时&#xff0c;资源消耗如何变化&#xff1f; 不同算法在极端情况下的性能差异有多大&#xff1f; 数学本质解析 复杂度函数 T(n)O(f(n))…

java多线程(7.0)

目录 ​编辑 定时器 定时器的使用 三.定时器的实现 MyTimer 3.1 分析思路 1. 创建执行任务的类。 2. 管理任务 3. 执行任务 3.2 线程安全问题 定时器 定时器是软件开发中的一个重要组件. 类似于一个 "闹钟". 达到一个设定的时间之后, 就执行某个指定好的…

Long类型封装Json传输时精度丢失问题

在信息做传输时&#xff0c;经常会使用到类型转换&#xff0c;这个时候因为一些问题会导致精度的丢失。在支付业务中这种问题更为致命。 这里我主动生成一个支付订单并将相关信息使用base64编码为一个二维码返回给前端进行支付&#xff0c;前端进行支付时我通过回调方法发现回调…

《从GPT崛起,看AI重塑世界》

《从GPT崛起,看AI重塑世界》 GPT 诞生:AI 领域的震撼弹 2022 年 11 月 30 日,OpenAI 发布了一款名为 ChatGPT 的人工智能聊天机器人程序,宛如一颗重磅炸弹投入了平静的湖面,迅速在全球范围内引发了轩然大波,成为了科技领域乃至大众舆论场中最热门的话题之一。一时间,无…

系统架构-安全架构设计

概述 对于信息系统来说&#xff0c;威胁有&#xff1a;物理环境&#xff08;最基础&#xff09;、通信链路、网络系统、操作系统、应用系统、管理系统 物理安全&#xff1a;系统所用设备的威胁&#xff0c;如自然灾害、电源故障通信链路安全&#xff1a;在传输线路上安装窃听…

鼠标指定范围内随机点击

鼠标指定范围内随机点击 点赞神器 将鼠标移动到相应位置后按F5 F6键&#xff0c;设置点击范围&#xff0c; F8开始&#xff0c;ESC中止。 有些直播有点赞限制&#xff0c;例如某音&#xff0c;每小时限制3千次&#xff0c;可以设置1200毫秒&#xff0c;3000次。 软件截图&#…

HashSet 概述

1. HashSet 概述 HashSet 是 Java 集合框架中 Set 接口的一个实现类&#xff0c;它存储唯一元素&#xff0c;即集合中不会有重复的元素。HashSet 基于哈希表&#xff08;实际上是 HashMap 实例&#xff09;来实现&#xff0c;不保证元素的顺序&#xff0c;并且允许存储 null 元…

遥测终端机,推动灌区流量监测向数据驱动跃迁

灌区范围那么大&#xff0c;每一滴水怎么流都关系到粮食够不够吃&#xff0c;还有生态能不能平衡。过去靠人工巡查、测量&#xff0c;就像拿着算盘想算明白大数据&#xff0c;根本满足不了现在水利管理的高要求。遥测终端机一出现&#xff0c;就像给灌区流量监测安上了智能感知…

蓝耘平台介绍:算力赋能AI创新的智算云平台

一、蓝耘平台是什么 蓝耘智算云&#xff08;LY Cloud&#xff09;是蓝耘科技打造的现代化GPU算力云服务平台&#xff0c;深度整合自研DS满血版大模型技术与分布式算力调度能力&#xff0c;形成"模型算力"双轮驱动的技术生态。平台核心优势如下&#xff1a; 平台定位…

QtDesigner中Button控件详解

一&#xff1a;Button控件 关于Button控件的主要作用就是作为触发开关&#xff0c;通过点击事件&#xff08;click&#xff09;执行代码逻辑&#xff0c;或者作为功能入口&#xff0c;跳转到其他界面或模块。 二&#xff1a;常见属性与配置 ①Button的enabled&#xff0c;大…

Flink 源码编译

打包命令 打包整个项目 mvn clean package -DskipTests -Drat.skiptrue打包单个模块 mvn clean package -DskipTests -Drat.skiptrue -pl flink-dist如果该模块依赖其他模块&#xff0c;可能需要先将其他模块 install 到本地&#xff0c;如果依赖的模块的源代码有修改&#…

docker的安装和简单使用(ubuntu环境)

环境准备 这里用的是linux的环境&#xff0c;如果没有云服务器的话&#xff0c;就是用虚拟环境吧。 虚拟环境的安装参考&#xff1a;vmware17的安装 linux镜像的安装 docker安装 我使用的是ubuntu&#xff0c;使用以下命令&#xff1a; 更新本地软件包索引 sudo apt u…

EasyRTC音视频实时通话在线教育解决方案:打造沉浸式互动教学新体验

一、方案概述 EasyRTC是一款基于WebRTC技术的实时音视频通信平台&#xff0c;为在线教育行业提供了高效、稳定、低延迟的互动教学解决方案。本方案将EasyRTC技术深度整合到在线教育场景中&#xff0c;实现师生间的实时音视频互动等核心功能&#xff0c;打造沉浸式的远程学习体…

【分布式系统中的“瑞士军刀”_ Zookeeper】一、Zookeeper 快速入门和核心概念

在分布式系统的复杂世界里&#xff0c;协调与同步是确保系统稳定运行的关键所在。Zookeeper 作为分布式协调服务的 “瑞士军刀”&#xff0c;为众多分布式项目提供了高效、可靠的协调解决方案。无论是在分布式锁的实现、配置管理&#xff0c;还是在服务注册与发现等场景中&…

Electron从入门到入门

项目说明 项目地址 项目地址&#xff1a;https://gitee.com/ruirui-study/electron-demo 本项目为示例项目&#xff0c;代码注释非常清晰&#xff0c;给大家当做入门项目吧。 其实很多东西都可以在我这基础上添加或修改、市面上有些已开源的项目&#xff0c;但是太臃肿了&am…

优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论

优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论 目录 优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论信息论信息熵明确问题主题提供具体细节限定回答方向规范语言表达概率论最优化理论信息论 原理:信息论中的熵可以衡量信息的不确定性。…

腾讯一面面经:总结一下

1. Java 中的 和 equals 有什么区别&#xff1f;比较对象时使用哪一个 1. 操作符&#xff1a; 用于比较对象的内存地址&#xff08;引用是否相同&#xff09;。 对于基本数据类型、 比较的是值。&#xff08;8种基本数据类型&#xff09;对于引用数据类型、 比较的是两个引…