设计模式——迭代器设计模式(行为型)

article/2025/7/14 1:42:48

摘要

本文详细介绍了迭代器设计模式,这是一种行为型设计模式,用于顺序访问集合对象中的元素,同时隐藏集合的内部结构。文章首先定义了迭代器设计模式并阐述了其核心角色,包括迭代器接口、具体迭代器、容器接口和具体容器。接着,文章通过 Java 标准库中的 Iterator 接口为例,展示了迭代器设计模式的结构和实现方式。此外,文章还探讨了迭代器设计模式的适用场景,包括适合和不适合使用该模式的情况,并通过金融风控的实战示例,展示了如何将迭代器设计模式与其他设计模式(如责任链模式、策略模式等)结合使用。最后,文章总结了迭代器设计模式与其他设计模式的组合使用方式。

1. 迭代器设计模式定义

迭代器设计模式(Iterator Pattern)是一种行为型设计模式,用于顺序访问一个集合对象中的元素,而又不暴露该对象的内部表示结构

1.1. 🔹 核心角色:

角色

说明

Iterator(迭代器接口)

定义访问和遍历元素的接口,如 hasNext()next()

ConcreteIterator(具体迭代器)

实现 Iterator接口,维护当前遍历位置。

Aggregate(容器接口)

定义创建迭代器对象的方法。

ConcreteAggregate(具体容器)

实现 Aggregate接口,返回该容器的迭代器。

Java 标准库中广泛使用了该模式,例如 java.util.Iterator 接口就是该模式的典型实现。

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

2. 迭代器设计模式结构

  1. 迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
  2. 具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
  3. 集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
  4. 具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。
  5. 客户端 (Client) 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。客户端通常不会自行创建迭代器, 而是会从集合中获取。 但在特定情况下, 客户端可以直接创建一个迭代器 (例如当客户端需要自定义特殊迭代器时)。

2.1. 迭代器类图

2.2. 迭代器时序图

3. 迭代器设计模式实现方式

迭代器设计模式的实现方式主要包括自定义以下四个关键角色:容器接口、具体容器、迭代器接口、具体迭代器。下面是标准的实现步骤(以 Java 为例)。

3.1. 🔹 定义迭代器接口 Iterator

public interface Iterator<T> {boolean hasNext();T next();
}

3.2. 🔹 定义聚合容器接口 Aggregate

public interface Aggregate<T> {Iterator<T> createIterator();
}

3.3. 🔹 实现具体容器 ConcreteAggregate

public class ConcreteAggregate<T> implements Aggregate<T> {private List<T> items = new ArrayList<>();public void add(T item) {items.add(item);}public T get(int index) {return items.get(index);}public int size() {return items.size();}@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(this);}
}

3.4. 🔹 实现具体迭代器 ConcreteIterator

public class ConcreteIterator<T> implements Iterator<T> {private ConcreteAggregate<T> aggregate;private int currentIndex = 0;public ConcreteIterator(ConcreteAggregate<T> aggregate) {this.aggregate = aggregate;}@Overridepublic boolean hasNext() {return currentIndex < aggregate.size();}@Overridepublic T next() {return aggregate.get(currentIndex++);}
}

3.5. 🔹 使用示例

public class Main {public static void main(String[] args) {ConcreteAggregate<String> container = new ConcreteAggregate<>();container.add("A");container.add("B");container.add("C");Iterator<String> iterator = container.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

3.6. ✅ 迭代器示例总结

组件

作用

Iterator 接口

提供统一遍历接口

ConcreteIterator

维护当前索引、实现遍历逻辑

Aggregate接口

提供创建迭代器方法

ConcreteAggregate

存储数据集合,并生成迭代器

4. 迭代器设计模式适合场景

迭代器设计模式的核心目的是提供统一的遍历接口,屏蔽容器内部的数据结构差异。下面是它适合与不适合的场景分析:

4.1. ✅ 适合使用迭代器设计模式的场景

场景

说明

容器类集合遍历

当你希望对集合(数组、列表、树、图等)进行遍历,不暴露其内部结构。

多种容器结构共用遍历方式

例如支持 ListSetMap、自定义集合类都实现一个标准的迭代器接口,便于切换。

需要多种遍历方式

如顺序、逆序、跳跃等不同的遍历策略,可以封装成不同的迭代器类。

自定义复杂聚合对象遍历

比如订单->商品->商品属性 这种层级结构,可以通过迭代器隐藏细节,统一接口。

希望解耦容器与遍历逻辑

把“遍历逻辑”从容器中抽离出来,符合单一职责、开闭原则。

支持多并发遍历操作

每个迭代器对象互不干扰,可以实现并发读操作。

4.2. ❌ 不适合使用迭代器设计模式的场景

场景

原因

集合结构非常简单,且不会改变

比如只有 1~2 个元素,直接使用 for-each 更高效,没必要引入额外迭代器类。

对遍历性能要求极高的系统(高频大数据处理)

自定义迭代器层级增加方法调用,可能影响性能,如在实时交易撮合、低延迟系统中。

对象间耦合必须最小,不能增加接口依赖

引入 Iterator接口会额外增加模块之间依赖,不符合某些架构设计原则。

需要对遍历过程进行复杂控制(如跳转、回溯)

此时可能更适合状态机模式或访问者模式,对每一步状态进行更复杂管理。

遍历逻辑需要携带大量上下文或中间状态

简单的迭代器不适合包含太多状态持久性,需要扩展为上下文感知处理器模式。

4.3. ✅ 举个金融风控例子

适合:遍历用户的多个信用卡账户,统一处理风控评分。

for (Account account : userAccountIterator) {scoreService.evaluate(account);
}

不适合:实时交易撮合引擎中,大量订单队列需要毫秒级处理,使用数组/队列遍历更高效,不宜引入自定义迭代器。

5. 迭代器设计模式实战示例

下面是一个在风控场景下,使用迭代器设计模式 + Spring 注解注入方式 实现的示例,适合处理多个风控规则依次执行的业务逻辑。

5.1. 🎯 场景描述

对信贷申请进行风控判断。每个申请会通过一系列规则(如年龄检查、信用分检查),每条规则是一个策略,同时这些策略按顺序组成一个责任链。为了支持动态控制规则顺序,还使用迭代器遍历规则链。

5.2. ☕️ 项目结构

com.example.risk
├── RiskRule.java         # 策略接口
├── AbstractRiskRule.java # 模板实现
├── BlackListRule.java    # 名单规则
├── AgeLimitRule.java     # 年龄限制规则
├── CreditScoreRule.java  # 信用分规则
├── RuleChainContext.java # 责任链 + 迭代器控制
├── RiskRequest.java      # 入参
├── RiskResponse.java     # 出参
├── RuleConfig.java       # 自动注入规则列表
└── RiskService.java      # 风控服务入口

5.3. 风控请求/响应对象

@Data
public class RiskRequest {private String userId;private int age;private int creditScore;private boolean inBlackList;
}@Data
public class RiskResponse {private boolean passed = true;private String failedReason;
}

5.4. 策略接口和抽象类(策略 + 模板)

public interface RiskRule {boolean evaluate(RiskRequest request, RiskResponse response);String getName();
}public abstract class AbstractRiskRule implements RiskRule {@Overridepublic boolean evaluate(RiskRequest request, RiskResponse response) {if (!doEvaluate(request)) {response.setPassed(false);response.setFailedReason(getName());return false;}return true;}protected abstract boolean doEvaluate(RiskRequest request);
}

5.5. 各种规则实现(策略 + 责任链)

@Component
public class BlackListRule extends AbstractRiskRule {@Overridepublic String getName() {return "黑名单规则";}@Overrideprotected boolean doEvaluate(RiskRequest request) {return !request.isInBlackList();}
}@Component
public class AgeLimitRule extends AbstractRiskRule {@Overridepublic String getName() {return "年龄限制规则";}@Overrideprotected boolean doEvaluate(RiskRequest request) {return request.getAge() >= 18;}
}@Component
public class CreditScoreRule extends AbstractRiskRule {@Overridepublic String getName() {return "信用分规则";}@Overrideprotected boolean doEvaluate(RiskRequest request) {return request.getCreditScore() >= 600;}
}

5.6. RuleChainContext(责任链 + 迭代器)

@Component
public class RuleChainContext {private final List<RiskRule> ruleList;@Autowiredpublic RuleChainContext(List<RiskRule> ruleList) {// 可排序或通过配置动态控制顺序this.ruleList = ruleList;}public RiskResponse process(RiskRequest request) {RiskResponse response = new RiskResponse();Iterator<RiskRule> iterator = ruleList.iterator();while (iterator.hasNext()) {// 迭代器进行遍历RiskRule rule = iterator.next();if (!rule.evaluate(request, response)) {break; // 短路失败}}return response;}
}

5.7. Service调用入口

@Service
public class RiskService {@Autowiredprivate RuleChainContext ruleChainContext;public RiskResponse evaluate(RiskRequest request) {return ruleChainContext.process(request);}
}

5.8. ✅ 使用方式示例

@RestController
@RequestMapping("/risk")
public class RiskController {@Autowiredprivate RiskService riskService;@PostMapping("/check")public RiskResponse check(@RequestBody RiskRequest request) {return riskService.evaluate(request);}
}

5.9. 🧠 总结:设计模式用法回顾

模式

用法说明

策略模式

每一个规则都是一个策略,实现 RiskRule接口

责任链模式

所有规则顺序执行,遇到失败立即终止

迭代器模式

通过 Iterator<RiskRule>遍历所有策略规则

模板方法模式

抽象类定义执行流程,子类重写核心判断逻辑

注解注入

使用 @Component+ @Autowired实现 Spring 自动装配

如需添加动态配置规则链顺序、启用规则开关、分组规则集等功能,可以进一步引入配置中心或数据库控制,支持高扩展。

6. 迭代器设计模式思考

6.1. 🔁 常与迭代器组合使用的设计模式

在实战开发中,迭代器设计模式(Iterator Pattern)通常与以下几种设计模式组合使用,以增强集合结构的灵活性、扩展性、解耦性,尤其在领域模型、规则处理、任务调度等系统中非常常见:

组合模式

搭配原因/典型场景

责任链模式

顺序执行规则或任务链,迭代器负责链路遍历

策略模式

每个元素是一个策略(如规则或算法),通过迭代器遍历并执行

组合模式

组合结构的子元素通过迭代器统一遍历(如树状结构遍历)

模板方法模式

元素结构统一,遍历时调用公共模板方法,保留定制扩展点

观察者模式

遍历一组观察者并触发通知

命令模式

遍历一组命令并逐一执行(或回滚)

装饰器模式

每一层装饰器通过迭代器包装组合

工厂方法模式

工厂批量创建可遍历的对象集合

6.1.1. 与责任链模式

场景:规则引擎、风控审核、流程编排

  • 每个 handler/规则实现 RuleHandler 接口
  • List<RuleHandler> 通过迭代器逐个执行,遇失败中断
for (RuleHandler handler : handlers) {if (!handler.handle(context)) {break;}
}

6.1.2. 与策略模式

场景:算法选择、数据转换器、规则过滤器

  • 每个元素是一个策略类(如计算利息、折扣策略)
  • 迭代器控制策略的执行顺序,支持动态扩展

6.1.3. 与组合模式

场景:菜单树、组织结构、数据表头嵌套结构

  • 组合结构的节点可以通过迭代器实现统一的遍历

6.1.4. 与模板方法模式

场景:日志采集、批量数据导出、统一操作步骤

  • 各子类复用固定遍历结构,通过 doXXX() 定制操作逻辑

6.1.5. 与命令模式

场景:批量命令处理、回滚事务、脚本执行

  • 一组命令对象放入集合,通过迭代器逐个执行或撤销

模式组合

是否常见

典型用途

迭代器 + 责任链

流程控制、规则判断

迭代器 + 策略

动态决策执行、多策略适配

迭代器 + 组合

树形结构统一遍历

迭代器 + 模板方法

标准流程 + 扩展处理

迭代器 + 命令

操作回放、事务控制

迭代器 + 观察者

🟡

通知一组监听者

迭代器 + 单例等

不适合,与集合行为无关

博文参考

  • 迭代器设计模式
  • 设计模式之迭代器模式 | DESIGN

http://www.hkcw.cn/article/EklaglZXJA.shtml

相关文章

【文献阅读】Learning Transferable Visual Models From Natural Language Supervision

摘要 最先进的计算机视觉系统经过训练&#xff0c;可预测一组固定的预先确定的对象类别。这种受限的监督形式限制了它们的通用性和可用性&#xff0c;因为指定任何其他视觉概念都需要额外的标记数据。 直接从关于图像的原始文本中学习是一种很有前途的替代方法&#xff0c;它…

字符函数和字符串函数

目录 1.字符分类函数 2.字符转换函数 3.strlen函数的使用和模拟实现 4.strcpy函数的使用和模拟实现 5.strcat函数的使用和模拟实现 6.strcmp函数的使用和模拟实现 7.strcnpy函数的使用和模拟实现 8.strcnat函数的使用和模拟实现 9.strncmp函数的使用 10.strstr的函数使…

苹果电脑深度清理,让老旧Mac重焕新生

在日常使用苹果电脑的过程中&#xff0c;随着时间推移&#xff0c;系统内会积累大量冗余数据&#xff0c;导致电脑运行速度变慢、磁盘空间紧张。想要让设备恢复流畅&#xff0c;苹果电脑深度清理必不可少。那么&#xff0c;如何进行苹果电脑深度清理呢&#xff1f;接下来为你详…

android binder(1)基本原理

一、IPC 进程间通信&#xff08;IPC&#xff0c;Inter-Process Communication&#xff09;机制&#xff0c;用于解决不同进程间的数据交互问题。 不同进程之间用户地址空间的变量和函数是不能相互访问的&#xff0c;但是不同进程的内核地址空间是相同和共享的&#xff0c;我们可…

2025年ESWA SCI1区TOP,改进成吉思汗鲨鱼算法MGKSO+肝癌疾病预测,深度解析+性能实测

1.摘要 本文针对肝癌&#xff08;HCC&#xff09;早期诊断难题&#xff0c;提出了一种基于改进成吉思汗鲨鱼优化算法&#xff08;MGKSO&#xff09;的计算机辅助诊断系统。由于HCC在早期症状不明显且涉及高维复杂数据&#xff0c;传统机器学习方法易受噪声和冗余特征干扰。为提…

性能测试实例(http和ldap协议压测)

一、某授权服务器生成授权码效率验证&#xff08;http协议&#xff09; 测试背景 在存量数据23万条的情况下&#xff0c;生成一条授权数据&#xff0c;需要10秒左右&#xff0c;用户反应数据生成效率太差&#xff0c;需要优化。初步判断是由于在授权数据生成时&#xff0c;有查…

解锁设计师创意魔法:Onlook赋能你的Web创作

在数字时代的今天&#xff0c;设计和开发的界限正在逐步模糊。无论是经验丰富的程序员&#xff0c;还是初出茅庐的设计师&#xff0c;能在统一的环境中高效实现创意是任何设计工具的理想。而Onlook&#xff0c;不仅是一个开源的视觉编码编辑器&#xff0c;更是一座连接设计与开…

智慧零工平台前端开发实战:从uni-app到跨平台应用

智慧零工平台前端开发实战:从uni-app到跨平台应用 本文将详细介绍我如何使用uni-app框架开发一个支持微信小程序和H5的零工平台前端应用,包含技术选型、架构设计、核心功能实现及部署经验。 前言 在当今移动互联网时代,跨平台开发已成为提高开发效率的重要手段。本次我选择…

用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包

在追求高性能的分布式系统中&#xff0c;RPC 框架的底层网络能力和数据传输效率起着决定性作用。经过几轮迭代优化&#xff0c;我完成了第四版本的 RPC 框架。相比以往版本&#xff0c;这一版本的最大亮点在于 重写了底层网络框架 和 实现了发送端的数据聚集机制&#xff0c;这…

云服务器突发宕机或无响应怎么办

当云服务器突发宕机或无响应时&#xff0c;需快速定位问题并恢复服务。以下是分步骤的解决方案&#xff1a; 1. 初步确认问题 检查网络连接 本地网络是否正常&#xff1f;尝试 ping 其他网站 排除本地问题。 使用 ping <服务器IP> 或 traceroute <IP> 测试网络连通…

掌握HttpClient技术:从基础到实战(Apache)

目录 前言 一、Apache HttpClient简介 二、HttpClient基础使用 1. 添加依赖 2. 创建HttpClient实例 3. 发送GET请求 4. 发送POST请求 三、HttpClient高级配置与实战案例 1. 连接池优化 2. 超时与重试配置 3. 文件上传&#xff08;Multipart&#xff09; 总结 前言 …

EXCEL--累加,获取大于某个值的第一个数

一、函数 LET(data,A1:A5,cumSum,SCAN(0,data,LAMBDA(a,b,ab)),idx,MATCH(TRUE,cumSum>C1,0),INDEX(data,idx)) 二、函数拆解 1、LET函数&#xff1a;LET(name1, value1, [name2, value2, ...], calculation) name1, name2...&#xff1a;自定义的变量名&#xff08;需以字…

D. Gellyfish and Camellia Japonica【Codeforces Round 1028 (Div. 2)】

D. Gellyfish and Camellia Japonica 思路 贪心构造&#xff08;其实是思维题&#xff09; 先找必要性&#xff0c;再验证充分性&#xff1a; 倒着求出每个位置的下界作为这个位置的值&#xff0c;再正着验证构造出的这个数列是否合法。 代码非常短&#xff0c;这个题如果当时…

GODOT引擎学习日志

最近在学习使用GODOT引擎&#xff0c;发现这个东西很好很强大。此为背景。 刚开始学习&#xff0c;在使用camera3D的时候&#xff0c;发现使用鼠标滚轮进行视角缩放的时候&#xff0c;网上有些内容不全&#xff0c;于是找了一下。其实很简单&#xff1a; Camera3D有个属性是siz…

普通二叉树 —— 最近公共祖先问题解析(Leetcode 236)

&#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 普通二叉树 —— 最近公共祖先问题解析&#xff08;Leetcode 236&#xff09;&#x1f9e0; 问题理解普通二叉树与 BST 的区别&#xff1a; &#x1f4a1; 解题思路关键思想&#xff1a;&#x1f4cc; 举个例子&#xff1a…

Dify 部署问题处理

Dify介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过程…

《操作系统真相还原》——中断

可以毫不夸张的说&#xff0c;操作系统离不开中断 此时我们将中断处理程序放在了汇编文件中了&#xff0c;很显然我们不能很方便的编写中断处理程序&#xff0c;不如在汇编程序里调用c函数。 在这个感觉过可以在c语言中直接内联汇编完成这些。 定时器 将时钟中断的频率提高后…

腾讯位置商业授权沿途搜索服务开发指南

概述 通过本服务检索某段道路附近的POI信息&#xff0c;可配合路线规划&#xff0c;为用户提供沿途服务区、加油站等搜索功能。 注&#xff1a; 1、本服务属于高级付费服务&#xff0c;如需试用请提交商务合作开通服务试用。 2、本接口有大小限制&#xff0c;接口长度不能超…

内容中台的实施基石是什么?

标准化流程体系构建 在企业内容中台建设中&#xff0c;标准化流程体系是确保内容生产、管理和分发效率的核心框架。通过定义元数据规范、内容分类规则及跨部门协作机制&#xff0c;能够实现从内容创建到归档的全链路标准化运作。例如&#xff0c;Baklib作为支持团队协作与权限…

信息安全管理与评估2024山东卷WAF答案

需要其他赛题解析的可联系博主