設計模式——迭代器設計模式(行為型)

摘要

本文詳細介紹了迭代器設計模式,這是一種行為型設計模式,用于順序訪問集合對象中的元素,同時隱藏集合的內部結構。文章首先定義了迭代器設計模式并闡述了其核心角色,包括迭代器接口、具體迭代器、容器接口和具體容器。接著,文章通過 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. 與命令模式

場景:批量命令處理、回滾事務、腳本執行

  • 一組命令對象放入集合,通過迭代器逐個執行或撤銷

模式組合

是否常見

典型用途

迭代器 + 責任鏈

?

流程控制、規則判斷

迭代器 + 策略

?

動態決策執行、多策略適配

迭代器 + 組合

?

樹形結構統一遍歷

迭代器 + 模板方法

?

標準流程 + 擴展處理

迭代器 + 命令

?

操作回放、事務控制

迭代器 + 觀察者

🟡

通知一組監聽者

迭代器 + 單例等

?

不適合,與集合行為無關

博文參考

  • 迭代器設計模式
  • 設計模式——迭代器設計模式(行為型)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83488.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83488.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83488.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java8 list集合根據屬性分組

在Java8中&#xff0c;可以使用Collectors.groupingBy方法對List集合根據屬性進行分組。以下是一個完整的示例&#xff0c;展示如何根據對象的不同屬性分組。 根據對象屬性分組 假設有一個Student類&#xff0c;包含name、age和grade屬性&#xff1a; public class Student …

更新已打包好的 Spring Boot JAR 文件中的 class 文件

# 1. 解壓原始 JAR unzip -q original-app.jar -d temp # 2. 替換 class 文件 cp ~/projects/new-classes/*.class temp/BOOT-INF/classes/com/example/ # 3. 保留原始清單 cp temp/META-INF/MANIFEST.MF . # 4. 重新打包 jar -cf0m new-app.jar MANIFEST.MF -C temp/ . # …

《HelloGitHub》第 110 期

興趣是最好的老師&#xff0c;HelloGitHub 讓你對開源感興趣&#xff01; 簡介 HelloGitHub 分享 GitHub 上有趣、入門級的開源項目。 github.com/521xueweihan/HelloGitHub 這里有實戰項目、入門教程、黑科技、開源書籍、大廠開源項目等&#xff0c;涵蓋多種編程語言 Python、…

當 “歐洲版 Cursor” 遇上安全危機

在 AI 編程助手蓬勃發展的當下&#xff0c;安全問題正成為行業不容忽視的隱憂。近期&#xff0c;AI 編程助手公司 Replit 與號稱 “歐洲版 Cursor” 的 Lovable 之間&#xff0c;因安全漏洞問題掀起了一場風波&#xff0c;引發了業界的廣泛關注。? Replit 的員工 Matt Palmer…

centos掛載目錄滿但實際未滿引發系統宕機

測試服務器應用系統突然掛了&#xff0c;經過排查發現是因為磁盤“滿了”導致的&#xff0c;使用df -h查看磁盤使用情況/home目錄使用率已經到了100%,但使用du -sh /home查看發現實際磁盤使用還不到1G&#xff0c;推測有進程正在寫入或占用已刪除的大文件&#xff08;Linux 系統…

乾坤qiankun的使用

vue2 為主應用 react 為子應用 在項目中安裝乾坤 yarn add qiankun # 或者 npm i qiankun -Svue主應用 在main.js中新增 &#xff08;需要注意的是路由模型為history模式&#xff09; registerMicroApps([{name: reactApp,entry: //localhost:3011,container: #container,/…

PostgreSQL的擴展 auth_delay

PostgreSQL的擴展 auth_delay auth_delay 是 PostgreSQL 提供的一個安全相關擴展&#xff0c;主要用于防止暴力破解攻擊。它通過在認證失敗后引入人為延遲來增加暴力破解的難度。 一、擴展基礎 功能&#xff1a;在認證失敗后增加延遲目的&#xff1a;減緩暴力破解和字典攻擊…

Web前端為什么要打包?Webpack 和 Vite 如何助力現代開發?

一. 為什么要使用框架庫? 1.1 傳統網頁與現代前端的差異 在最早期的網頁開發中,我們只需要寫幾個.html文件,配上.css和.js文件,瀏覽器直接加載就能展現頁面,每個文件都是獨立的靜態資源,簡單且直觀 但現在網站越來越復雜了: 需要用到最新的js語法(比如ES6)使用框架(Vue…

使用pdm+uv替換poetry

用了好幾年poetry了&#xff0c;各方面都還挺滿意&#xff0c;就是lock實在太慢&#xff1b; 已經試用pdmuv一段時間了&#xff0c;確實是快&#xff0c;也基本能覆蓋poetry的功能。 至于為什么用pdmuv&#xff0c;而不是只用uv&#xff0c;原因很多&#xff0c;有興趣的可以…

java后端生成心電圖-jfreechart

用jfreechart生成心電圖 先上成功的圖片 上代碼 1.導入包 implementation org.jfree:jfreechart:1.5.4implementation org.jfree:jcommon:1.0.242.實現代碼 對數據進行濾波 轉換單位 package com.shinrun.infrastructure.util;import java.util.ArrayList; import java.ut…

微軟Build 2025:Copilot Studio升級,解鎖多智能體協作未來

微軟Build 2025大會圓滿落幕&#xff0c;作為年度科技盛會&#xff0c;它一直是開發與AI技術突破性創新的重要展示平臺。對于工程師、創作者和領域專家來說&#xff0c;這是了解微軟生態未來動向的關鍵時刻。今年&#xff0c;Microsoft Copilot Studio推出了一系列新功能&#…

LabVIEW雜草識別與精準噴灑

基于LabVIEW構建了一套集成機器視覺、智能決策與精準控制的農業雜草識別系統。通過高分辨率視覺傳感器采集作物圖像&#xff0c;利用 LabVIEW 的 NI Vision 模塊實現圖像顏色匹配與特征分析&#xff0c;結合 Arduino 兼容的工業級控制硬件&#xff0c;實現雜草定位與除草劑精準…

使用 Akamai 分布式云與 CDN 保障視頻供稿傳輸安全

作者簡介&#xff1a;David Eisenbacher 是 EZDRM 公司的首席執行官兼聯合創始人&#xff0c;該公司是首家提供 "DRM 即服務" 的企業。作為 CEO&#xff0c;David 始終秉持為企業確立的使命&#xff1a;為視頻服務商提供簡潔有效的數字版權管理方案&#xff0c;助力其…

javascript 實戰案例 二級聯動下拉選框

本案例完全使用原生javascript實現&#xff0c;使用時只需填充platform_list二維數組即可&#xff0c;platform_list填充規則如下&#xff1a; [‘一級選項1’,‘二級選項11’,‘二級選項12’,‘二級選項13’,‘二級選項14’,…], [‘一級選項2’,‘二級選項21’,‘二級選項22’…

Elasticsearch集群最大分片數設置詳解:從問題到解決方案

目錄 前言 1 問題背景&#xff1a;重啟后設置失效 2 核心概念解析 2.1 什么是分片(Shard)&#xff1f; 2.2 cluster.max_shards_per_node的作用 2.3 默認值是多少&#xff1f; 3 參數設置的兩種方式 3.2 持久性設置(persistent) 3.2 臨時設置(transient) 4 問題解決方…

Redis Sorted Set 深度解析:從原理到實戰應用

Redis Sorted Set 深度解析&#xff1a;從原理到實戰應用 在 Redis 豐富的數據結構家族中&#xff0c;Sorted Set&#xff08;有序集合&#xff09;憑借獨特的設計和強大的功能&#xff0c;成為處理有序數據場景的得力工具。無論是構建實時排行榜&#xff0c;還是實現基于時間的…

Java并發編程:讀寫鎖與普通互斥鎖的深度對比

在Java并發編程中&#xff0c;鎖是實現線程安全的重要工具。其中&#xff0c;普通互斥鎖&#xff08;如synchronized和ReentrantLock&#xff09;和讀寫鎖&#xff08;ReentrantReadWriteLock&#xff09;是兩種常用的同步機制。本文將從多個維度深入分析它們的區別、適用場景及…

《云原生安全攻防》-- K8s網絡策略:通過NetworkPolicy實現微隔離

默認情況下&#xff0c;K8s集群的網絡是沒有任何限制的&#xff0c;所有的Pod之間都可以相互訪問。這就意味著&#xff0c;一旦攻擊者入侵了某個Pod&#xff0c;就能夠訪問到集群中任意Pod&#xff0c;存在比較大的安全風險。 在本節課程中&#xff0c;我們將詳細介紹如何通過N…

Log4j2、Fastjson特征流量分析

文章目錄 一、Log4j2流量特征分析1. 漏洞原理簡述2. 核心流量特征&#xff08;1&#xff09;請求特征&#xff08;2&#xff09;響應特征&#xff08;3&#xff09;日志特征 3.檢測與防御建議 二、fastjson流量特征分析1.漏洞原理簡述2.核心流量特征&#xff08;1&#xff09;請…

Java編程之建造者模式

建造者模式&#xff08;Builder Pattern&#xff09;是一種創建型設計模式&#xff0c;它將一個復雜對象的構建與表示分離&#xff0c;使得同樣的構建過程可以創建不同的表示。這種模式允許你分步驟構建一個復雜對象&#xff0c;并且可以在構建過程中進行不同的配置。 模式的核…