摘要
本文詳細介紹了迭代器設計模式,這是一種行為型設計模式,用于順序訪問集合對象中的元素,同時隱藏集合的內部結構。文章首先定義了迭代器設計模式并闡述了其核心角色,包括迭代器接口、具體迭代器、容器接口和具體容器。接著,文章通過 Java 標準庫中的 Iterator 接口為例,展示了迭代器設計模式的結構和實現方式。此外,文章還探討了迭代器設計模式的適用場景,包括適合和不適合使用該模式的情況,并通過金融風控的實戰示例,展示了如何將迭代器設計模式與其他設計模式(如責任鏈模式、策略模式等)結合使用。最后,文章總結了迭代器設計模式與其他設計模式的組合使用方式。
1. 迭代器設計模式定義
迭代器設計模式(Iterator Pattern)是一種行為型設計模式,用于順序訪問一個集合對象中的元素,而又不暴露該對象的內部表示結構。
1.1. 🔹 核心角色:
角色 | 說明 |
Iterator(迭代器接口) | 定義訪問和遍歷元素的接口,如 |
ConcreteIterator(具體迭代器) | 實現 |
Aggregate(容器接口) | 定義創建迭代器對象的方法。 |
ConcreteAggregate(具體容器) | 實現 |
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. 迭代器設計模式結構
- 迭代器 (Iterator) 接口聲明了遍歷集合所需的操作: 獲取下一個元素、 獲取當前位置和重新開始迭代等。
- 具體迭代器 (Concrete Iterators) 實現遍歷集合的一種特定算法。 迭代器對象必須跟蹤自身遍歷的進度。 這使得多個迭代器可以相互獨立地遍歷同一集合。
- 集合 (Collection) 接口聲明一個或多個方法來獲取與集合兼容的迭代器。 請注意, 返回方法的類型必須被聲明為迭代器接口, 因此具體集合可以返回各種不同種類的迭代器。
- 具體集合 (Concrete Collections) 會在客戶端請求迭代器時返回一個特定的具體迭代器類實體。 你可能會琢磨, 剩下的集合代碼在什么地方呢? 不用擔心, 它也會在同一個類中。 只是這些細節對于實際模式來說并不重要, 所以我們將其省略了而已。
- 客戶端 (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. ? 迭代器示例總結
組件 | 作用 |
| 提供統一遍歷接口 |
| 維護當前索引、實現遍歷邏輯 |
| 提供創建迭代器方法 |
| 存儲數據集合,并生成迭代器 |
4. 迭代器設計模式適合場景
迭代器設計模式的核心目的是提供統一的遍歷接口,屏蔽容器內部的數據結構差異。下面是它適合與不適合的場景分析:
4.1. ? 適合使用迭代器設計模式的場景
場景 | 說明 |
? 容器類集合遍歷 | 當你希望對集合(數組、列表、樹、圖等)進行遍歷,不暴露其內部結構。 |
? 多種容器結構共用遍歷方式 | 例如支持 |
? 需要多種遍歷方式 | 如順序、逆序、跳躍等不同的遍歷策略,可以封裝成不同的迭代器類。 |
? 自定義復雜聚合對象遍歷 | 比如訂單->商品->商品屬性 這種層級結構,可以通過迭代器隱藏細節,統一接口。 |
? 希望解耦容器與遍歷邏輯 | 把“遍歷邏輯”從容器中抽離出來,符合單一職責、開閉原則。 |
? 支持多并發遍歷操作 | 每個迭代器對象互不干擾,可以實現并發讀操作。 |
4.2. ? 不適合使用迭代器設計模式的場景
場景 | 原因 |
? 集合結構非常簡單,且不會改變 | 比如只有 1~2 個元素,直接使用 for-each 更高效,沒必要引入額外迭代器類。 |
? 對遍歷性能要求極高的系統(高頻大數據處理) | 自定義迭代器層級增加方法調用,可能影響性能,如在實時交易撮合、低延遲系統中。 |
? 對象間耦合必須最小,不能增加接口依賴 | 引入 |
? 需要對遍歷過程進行復雜控制(如跳轉、回溯) | 此時可能更適合狀態機模式或訪問者模式,對每一步狀態進行更復雜管理。 |
? 遍歷邏輯需要攜帶大量上下文或中間狀態 | 簡單的迭代器不適合包含太多狀態持久性,需要擴展為上下文感知處理器模式。 |
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. 🧠 總結:設計模式用法回顧
模式 | 用法說明 |
策略模式 | 每一個規則都是一個策略,實現 |
責任鏈模式 | 所有規則順序執行,遇到失敗立即終止 |
迭代器模式 | 通過 |
模板方法模式 | 抽象類定義執行流程,子類重寫核心判斷邏輯 |
注解注入 | 使用 |
如需添加動態配置規則鏈順序、啟用規則開關、分組規則集等功能,可以進一步引入配置中心或數據庫控制,支持高擴展。
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. 與命令模式
場景:批量命令處理、回滾事務、腳本執行
- 一組命令對象放入集合,通過迭代器逐個執行或撤銷
模式組合 | 是否常見 | 典型用途 |
迭代器 + 責任鏈 | ? | 流程控制、規則判斷 |
迭代器 + 策略 | ? | 動態決策執行、多策略適配 |
迭代器 + 組合 | ? | 樹形結構統一遍歷 |
迭代器 + 模板方法 | ? | 標準流程 + 擴展處理 |
迭代器 + 命令 | ? | 操作回放、事務控制 |
迭代器 + 觀察者 | 🟡 | 通知一組監聽者 |
迭代器 + 單例等 | ? | 不適合,與集合行為無關 |