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

设计模式(十七)行为型:迭代器模式详解

设计模式(十七)行为型:迭代器模式详解

迭代器模式(Iterator Pattern)是 GoF 23 种设计模式中的行为型模式之一,其核心价值在于提供一种统一的方式遍历聚合对象(如集合、容器)中的元素,而无需暴露其内部表示结构。它将遍历算法从聚合对象中分离出来,封装在独立的迭代器对象中,实现了“单一职责原则”和“开闭原则”。迭代器模式是现代编程语言集合框架的基石,广泛应用于各种数据结构(列表、树、图、哈希表)的遍历操作,是实现 for-each 循环、流式处理(Stream)、延迟计算、外部迭代等机制的核心支撑,是构建可复用、可扩展、高内聚低耦合系统的必备设计模式。

一、详细介绍

迭代器模式解决的是“客户端需要访问聚合对象中的所有元素,但又不希望依赖其内部实现细节”的问题。在传统设计中,聚合类(如 ListTree)通常提供 get(i)elements() 等方法让客户端直接访问内部数据,这导致:

  • 客户端代码与聚合的内部结构(数组、链表、树)紧耦合;
  • 聚合类职责过重,既管理数据又提供遍历逻辑;
  • 难以支持多种遍历方式(如正序、逆序、深度优先、广度优先);
  • 并发修改时难以保证遍历的安全性。

迭代器模式通过引入一个独立的迭代器对象(Iterator) 来封装遍历过程。客户端通过迭代器提供的统一接口(如 hasNext()next())访问元素,而无需关心底层是数组、链表还是树。聚合对象(Aggregate)负责创建并返回一个合适的迭代器实例。

该模式包含以下核心角色:

  • Iterator(迭代器接口):定义遍历聚合对象所需的操作,通常包括:
    • hasNext():判断是否还有下一个元素。
    • next():返回当前元素并将游标移至下一个。
    • remove()(可选):移除当前元素(Java 中常见)。
  • ConcreteIterator(具体迭代器):实现 Iterator 接口,针对特定聚合结构(如数组、链表)实现具体的遍历逻辑。它持有对聚合对象的引用或内部状态(如索引、当前节点)。
  • Aggregate(聚合接口):定义创建迭代器的方法,通常为 createIterator()
  • ConcreteAggregate(具体聚合类):实现 Aggregate 接口,返回一个与自身结构匹配的 ConcreteIterator 实例。
  • Client(客户端):通过聚合对象获取迭代器,并使用迭代器接口遍历元素。

迭代器模式的关键优势:

  • 解耦聚合与遍历:客户端不依赖聚合的内部结构。
  • 支持多种遍历方式:同一聚合可提供多种迭代器(如正序、逆序、过滤迭代器)。
  • 简化客户端代码:提供统一的遍历接口。
  • 支持并发安全遍历:迭代器可实现“快照”或“失败快速”机制(如 Java 的 ConcurrentModificationException)。
  • 支持延迟计算(Lazy Evaluation):元素可在 next() 调用时动态生成(如数据库游标、无限序列)。

与“访问者模式”相比,迭代器关注线性访问元素,访问者关注在不修改类的前提下为对象结构添加新操作;与“生成器模式”相比,生成器用于创建复杂对象,迭代器用于访问已有对象集合

迭代器可分为:

  • 外部迭代器(External Iterator):客户端主动控制遍历过程(如 while(it.hasNext()))。
  • 内部迭代器(Internal Iterator):由聚合或迭代器内部控制遍历,客户端提供回调(如 Java 8 的 forEach(Consumer)),更接近“函数式编程”。

二、迭代器模式的UML表示

以下是迭代器模式的标准 UML 类图:

implements
implements
has a
gets iterator
uses for traversal
«interface»
Iterator
+hasNext()
+next()
+remove()
ConcreteIterator
-aggregate: ConcreteAggregate
-currentIndex: int
+hasNext()
+next()
+remove()
«interface»
Aggregate
+createIterator()
ConcreteAggregate
-items: List<Object>
+createIterator()
Client
+main(args: String[])

图解说明

  • Iterator 定义统一遍历接口。
  • ConcreteIterator 针对 ConcreteAggregate 实现具体遍历逻辑。
  • ConcreteAggregate 实现 createIterator() 返回其对应的迭代器。
  • Client 通过聚合获取迭代器并遍历。

三、一个简单的Java程序实例及其UML图

以下是一个自定义的 BookShelf 聚合类,使用迭代器模式遍历书架上的书籍。

Java 程序实例
import java.util.ArrayList;
import java.util.List;// 书籍类
class Book {private String title;private String author;public Book(String title, String author) {this.title = title;this.author = author;}// Getter 方法public String getTitle() { return title; }public String getAuthor() { return author; }@Overridepublic String toString() {return "\"" + title + "\" by " + author;}
}// 迭代器接口
interface Iterator<T> {boolean hasNext();T next();
}// 聚合接口
interface Aggregate<T> {Iterator<T> createIterator();
}// 具体聚合类:书架
class BookShelf implements Aggregate<Book> {private List<Book> books = new ArrayList<>();public void addBook(Book book) {books.add(book);}public int getSize() {return books.size();}public Book getBookAt(int index) {return books.get(index);}// 实现创建迭代器@Overridepublic Iterator<Book> createIterator() {return new BookShelfIterator(this);}
}// 具体迭代器:书架迭代器
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() {if (!hasNext()) {throw new java.util.NoSuchElementException();}Book book = bookShelf.getBookAt(currentIndex);currentIndex++;return book;}
}// 客户端使用示例
public class IteratorPatternDemo {public static void main(String[] args) {System.out.println("📚 书架管理系统 - 迭代器模式示例\n");// 创建书架并添加书籍BookShelf bookShelf = new BookShelf();bookShelf.addBook(new Book("设计模式", "GoF"));bookShelf.addBook(new Book("重构", "Martin Fowler"));bookShelf.addBook(new Book("代码大全", "Steve McConnell"));// 获取迭代器Iterator<Book> iterator = bookShelf.createIterator();System.out.println("📖 正在遍历书架中的书籍:");while (iterator.hasNext()) {Book book = iterator.next();System.out.println("  ➡️ " + book);}System.out.println("\n✅ 遍历完成!");// 演示:可轻松替换为其他迭代器(如逆序)// 若实现 ReverseBookShelfIterator,只需替换 createIterator() 返回即可System.out.println("\n💡 说明:客户端代码无需修改即可支持不同遍历方式。");System.out.println("🔧 迭代器封装了遍历细节,书架内部可改为链表、树等结构。");}
}
实例对应的UML图(简化版)
implements
implements
has a
creates
gets iterator
uses for traversal
Book
-title: String
-author: String
+getTitle()
+getAuthor()
«interface»
Iterator<T>
+hasNext()
+next()
«interface»
Aggregate<T>
+createIterator()
BookShelf
-books: List<Book>
+addBook(book: Book)
+getSize()
+getBookAt(index: int)
+createIterator()
BookShelfIterator
-bookShelf: BookShelf
-currentIndex: int
+hasNext()
+next()
Client
+main(args: String[])

运行说明

  • BookShelf 是具体聚合类,内部使用 List<Book> 存储书籍。
  • BookShelfIterator 是具体迭代器,持有对 BookShelf 的引用和当前索引。
  • 客户端通过 createIterator() 获取迭代器,使用 hasNext()next() 安全遍历,无需知道 BookShelf 使用 List 实现。

四、总结

特性说明
核心目的统一访问聚合元素,隐藏内部结构
实现机制迭代器对象封装遍历状态与逻辑
优点解耦、支持多遍历方式、简化客户端、支持延迟计算
缺点增加类数量、可能增加内存开销(迭代器对象)
适用场景集合遍历、树/图遍历、数据库游标、流处理、外部API数据访问
不适用场景遍历逻辑极其简单、性能极度敏感(少量元素)

迭代器模式使用建议

  • Java 集合框架(Collection/Iterator)是迭代器模式的标准实现。
  • 可实现只读迭代器可移除迭代器过滤迭代器转换迭代器等变体。
  • 支持泛型以提高类型安全。
  • 注意并发修改问题,可实现“快照迭代器”或“失败快速”机制。

架构师洞见:
迭代器模式是“关注点分离”与“接口抽象”的典范。在现代架构中,其思想已演变为流式编程(Stream API)响应式编程(Reactive Streams)数据管道的核心。例如,Java 8 的 Stream 是迭代器的高级抽象,支持链式操作(filter, map, reduce);在大数据处理中,Iterator 是处理海量数据流的基础(如 Hadoop RecordReader);在微服务中,分页 API 的 nextPageToken 本质是分布式迭代器;在前端框架中,虚拟列表(Virtual List)使用迭代器思想按需渲染。

未来趋势是:迭代器将与函数式编程深度融合,支持更复杂的组合操作;在AI 数据处理中,数据集迭代器(如 PyTorch DataLoader)是训练模型的关键;在边缘计算中,迭代器可实现低内存的流式数据处理;在量子计算中,状态叠加的遍历可能需要新型迭代器。

掌握迭代器模式,有助于设计出高内聚、低耦合、可复用的集合组件。作为架构师,应在设计任何容器类或数据访问层时,主动考虑使用迭代器。迭代器不仅是模式,更是数据访问的哲学——它告诉我们:真正的抽象,不在于隐藏数据,而在于提供一种安全、统一、可组合的方式来消费数据,让使用者专注于“做什么”,而非“如何做”。

http://www.xdnf.cn/news/1202671.html

相关文章:

  • react前端样式如何给元素设置高度自适应
  • debian系统分卷是不会影响系统启动速度?
  • 内存分页机制分析在海外VPS系统的测试流程
  • C语言:20250728学习(指针)
  • 如何给电脑换个ip地址?电脑换ip几种方法
  • 从零开始的云计算生活——第三十七天,跬步千里,ansible之playbook
  • linux_centos7安装jdk8_采用jdk安装包安装
  • 电脑出现英文字母开不了机怎么办 原因与修复方法
  • 【Java EE】多线程-初阶-线程的状态
  • 云原生作业(haproxy)
  • 设计模式十二:门面模式 (FaçadePattern)
  • C++11之lambda及包装器
  • java设计模式 -【责任链模式】
  • 【智慧物联网平台】编译jar环境 Linux 系统Maven 安装——仙盟创梦IDE
  • RK3568基于mpp实现硬解码(二):FFmpeg + mpp实现ipc摄像头图像解码
  • C++---初始化列表(initializer_list)
  • maven 打包报错 process terminated
  • 数据库原理
  • MCP资源管理深度实践:动态数据源集成方案
  • 终结集成乱局:模型上下文协议(MCP)如何重构AI工具生态?
  • 深入探索Linux:忙碌的车间“进程”间通信
  • 四、计算机组成原理——第6章:总线
  • 微信小程序——早餐小程序
  • LeetCode 85. 最大矩形
  • 「源力觉醒 创作者计划」_文心大模型4.5系列开源模型,意味着什么?对开发者、对行业生态有何影响?
  • SpringBoot 发送邮件
  • Datawhale AI夏令营--Task2:理解项目目标、从业务理解到技术实现!
  • 数值计算 | 图解基于龙格库塔法的微分方程计算与连续系统离散化(附Python实现)
  • MQTT之“SUBSCRIBE报文和SUBACK报文”
  • “太赫兹”