引言:
走進圖書館,你站在一排書架前,想要瀏覽書籍。你會一格格地從左到右翻閱書籍,而不是去研究書架是什么。
一本書一本書地翻,才知道書架上藏了什么書,研究書架的構造是不知道書籍的內容的。
這種“逐本訪問,但不關心內部結構”的方式,正是迭代器模式所解決的問題。
一、什么是迭代器模式
迭代器模式(Iterator Pattern)是一種行為型設計模式,它用于順序訪問一個聚合對象(如集合、數組、列表等)中的元素,而不暴露其內部實現結構。
如同在圖書館看書,你只需一格一格地取書,不必關心書架內部是怎么存放書的。
二、模式結構與角色分工
我們以 Java 中模擬的“書架 BookShelf”為例,來理解迭代器模式的標準結構:
結構角色:
角色 | 作用說明 |
---|---|
Iterator | 定義遍歷行為接口,如 hasNext() 和 next() |
ConcreteIterator | 實現具體的遍歷邏輯 |
Aggregate | 表示可被遍歷的聚合容器 |
ConcreteAggregate | 實現具體容器,如 BookShelf |
Client | 客戶端,使用迭代器來遍歷聚合對象 |
三、UML 類圖(PlantUML)
如下為UML結構圖:
四、完整 Java 示例:
實現一個支持迭代的“書架”,來實現書架與書的迭代器。
定義迭代器接口
public interface Iterator<T> {boolean hasNext();T next();
}
定義聚合接口
public interface Aggregate<T> {Iterator<T> createIterator();
}
實體類:書 Book
public class Book {private final String name;public Book(String name) {this.name = name;}public String getName() {return name;}
}
聚合類:書架 BookShelf
public class BookShelf implements Aggregate<Book> {private final Book[] books;private int last = 0;public BookShelf(int maxSize) {books = new Book[maxSize];}public void appendBook(Book book) {books[last++] = book;}public Book getBookAt(int index) {return books[index];}public int getLength() {return last;}@Overridepublic Iterator<Book> createIterator() {return new BookShelfIterator(this);}
}
具體迭代器:BookShelfIterator
public class BookShelfIterator implements Iterator<Book> {private final BookShelf bookShelf;private int index = 0;public BookShelfIterator(BookShelf bookShelf) {this.bookShelf = bookShelf;}@Overridepublic boolean hasNext() {return index < bookShelf.getLength();}@Overridepublic Book next() {return bookShelf.getBookAt(index++);}
}
客戶端使用示例
public class Main {public static void main(String[] args) {BookShelf shelf = new BookShelf(5);shelf.appendBook(new Book("Java 入門"));shelf.appendBook(new Book("設計模式"));shelf.appendBook(new Book("數據結構"));Iterator<Book> iterator = shelf.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next().getName());}}
}
五、優點與適用場景
優點
迭代器模式的 5 大優勢
優點點名 | 詳細說明 |
---|---|
封裝遍歷邏輯 | 遍歷算法被封裝在 Iterator 中,不暴露集合內部結構(如數組、鏈表),提高封裝性和模塊化。 |
統一遍歷接口 | 客戶端代碼只需依賴統一的 hasNext() + next() 接口,遍歷不同類型集合(數組、列表、集合)方式一致,降低學習和使用成本。 |
解耦數據與操作 | 將“存儲數據”與“遍歷行為”解耦,使集合可以專注于數據存儲,迭代器專注于遍歷策略。可獨立擴展遍歷方式,而不破壞集合類結構。 |
支持多種遍歷策略 | 可以擴展出不同的迭代器實現,如: 正向遍歷 反向遍歷 跳步遍歷(隔一個取一個) 過濾遍歷(如只遍歷奇數) |
組合結構遍歷利器 | 在樹形結構、圖結構、目錄結構(如菜單、文件系統)中,也能借助迭代器實現統一的訪問方式,特別適合組合模式聯合使用。 |
適用場景詳解
應用情境 | 舉例說明 |
---|---|
不想暴露集合內部結構 | 比如使用數組或鏈表實現的容器,客戶端不應訪問 books[i] 或 nextNode ,而只應通過迭代器獲取元素。 |
希望集合類與遍歷邏輯解耦 | 當你需要根據數據源切換不同存儲實現時(比如數組 ? 鏈表 ? 棧),客戶端代碼不應受影響,只需提供新的迭代器實現。 |
有多種遍歷需求時 | 如:分頁展示(一次顯示10條)、篩選遍歷(只顯示評分大于4的書)、逆序瀏覽等。 |
需要統一接口處理不同容器 | 你希望能一套邏輯遍歷多個不同集合對象(如 List、Set、自定義容器),通過統一接口提高代碼復用性。 |
希望組合結構對象支持遍歷 | 在文件目錄、組織架構樹、菜單欄中,想要統一地“層層展開瀏覽”,迭代器是組合模式的理想搭檔。 |
開發腳本解釋器、編譯器 | 語言處理器中常常要遍歷語法樹(AST),語法元素集合可以通過迭代器統一訪問,提高程序可擴展性。 |
六、在JDK 的使用
Java 中的 java.util.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());
}
只需要關注 元素如何一個個訪問,而不關心其他因素。
總結
項目 | 內容 |
---|---|
模式名稱 | 迭代器模式(Iterator Pattern) |
類型 | 行為型模式 |
典型用途 | 遍歷集合,不暴露內部結構 |
Java 支持 | java.util.Iterator 接口 |
類比說明 | 一本本地翻閱圖書館書架上的書 |
參考
《23種設計模式概覽》