定義
迭代器模式(Iterator Pattern)是一種行為型設計模式,用于順序訪問集合對象的元素,而無需知道集合對象的底層表示。迭代器模式將遍歷集合的責任從集合對象轉移到迭代器對象上,這簡化了集合接口和實現,同時也使得遍歷不同的集合類型統一和標準化。
迭代器模式主要涉及以下角色:
- 迭代器(Iterator)接口:定義訪問和遍歷元素的接口。
- 具體迭代器(Concrete Iterator):實現迭代器接口,并負責遍歷集合的具體對象。
- 集合(Aggregate)接口:定義創建迭代器對象的接口。
- 具體集合(Concrete Aggregate):實現創建迭代器對象的接口,返回一個適合該集合的具體迭代器實例。
- 客戶端(Client):使用迭代器接口訪問集合元素。
解決的問題
- 統一的遍歷方式:提供一種統一的方法來遍歷各種類型的集合對象,而不暴露其內部結構。
- 解耦集合對象和遍歷邏輯:將集合的遍歷邏輯從集合對象中分離出來,使得集合對象和遍歷邏輯之間的職責更加清晰。
- 支持多種遍歷:可以定義多種遍歷方式,每種方式對應一個迭代器實現。
使用場景
- 不同的方式遍歷集合:當集合對象需要提供多種遍歷方式時,迭代器模式提供了一種靈活的解決方案。
- 訪問集合的內容而無需暴露其內部結構:當需要提供一種標準的方式來遍歷集合,而又不希望暴露集合的內部表示時。
- 允許在不同的集合類型上進行遍歷:迭代器模式可以在不同類型的集合對象上實現統一的遍歷接口。
示例代碼
// 迭代器接口
public interface Iterator {boolean hasNext();Object next();
}// 集合接口
public interface Container {Iterator getIterator();
}// 具體集合實現
class NameRepository implements Container {public String names[] = {"Robert", "John", "Julie", "Lora"};@Overridepublic Iterator getIterator() {return new NameIterator();}// 內部類實現具體迭代器private class NameIterator implements Iterator {int index;@Overridepublic boolean hasNext() {return index < names.length;}@Overridepublic Object next() {if (this.hasNext()) {return names[index++];}return null;}}
}// 客戶端使用迭代器
public class IteratorPatternDemo {public static void main(String[] args) {NameRepository namesRepository = new NameRepository();for (Iterator iter = namesRepository.getIterator(); iter.hasNext();) {String name = (String)iter.next();System.out.println("Name : " + name);}}
}
主要符合的設計原則
- 單一職責原則(Single Responsibility Principle):
- 迭代器模式將數據的遍歷和業務邏輯分離。容器只負責管理元素,而迭代器負責遍歷這些元素。這種分離確保了每個類都只有一個改變的原因,迭代器負責遍歷邏輯,而容器類負責管理集合。
- 開閉原則(Open-Closed Principle):
- 該模式允許在不修改現有集合對象的情況下引入新的迭代器類型。例如,你可以引入一個新的迭代器來遍歷容器中的元素,而無需修改容器類的代碼。因此,容器類對擴展是開放的,但對修改是封閉的。
- 迪米特法則(Law of Demeter)或最少知識原則:
- 迭代器模式允許客戶端代碼僅與迭代器對象交互,而不需要直接處理集合內部的細節。這符合迪米特法則,即一個對象應該盡量少地了解其他對象。
- 里氏替換原則(Liskov Substitution Principle):
- 如果迭代器有一個基類或接口,那么其不同的實現(例如前向迭代器、后向迭代器或隨機訪問迭代器)可以互換使用,而不影響客戶端代碼的運行。這符合里氏替換原則,因為子類迭代器可以替換基類迭代器。
在JDK中的應用
- Java Collections Framework:
- 幾乎所有的集合類(如
ArrayList
,HashSet
,LinkedList
等)都通過Iterator
接口提供了迭代器。這些集合類的iterator()
方法返回一個實現了Iterator
接口的對象,用于遍歷集合中的元素。
- 幾乎所有的集合類(如
- java.util.Iterator:
- 這是迭代器模式的核心接口。它定義了
next()
,hasNext()
, 和remove()
等方法,用于遍歷集合并在必要時刪除元素。
- 這是迭代器模式的核心接口。它定義了
- java.util.ListIterator:
ListIterator
是Iterator
接口的擴展,專門用于列表的雙向遍歷。除了標準的迭代器操作外,它還支持向前遍歷、修改元素和獲取元素的索引。
- java.util.Enumeration:
- 雖然現在已經不常用,
Enumeration
是早期Java版本中的一種迭代器,用于遍歷例如Vector
和Hashtable
這樣的數據結構。
- 雖然現在已經不常用,
- java.util.Scanner:
Scanner
類在某種程度上也實現了迭代器模式。它可以對輸入進行解析,并以迭代的方式返回輸入的各個部分(如通過next()
方法)。
- java.nio.file.DirectoryStream:
- 在NIO文件系統中,
DirectoryStream
接口用于遍歷目錄中的文件。它提供了一個迭代器來訪問目錄中的每個文件。
- 在NIO文件系統中,
在Spring中的應用
- Spring的資源處理:
- Spring提供了對資源的抽象,比如
Resource
接口和ResourceLoader
。在處理資源集合時,比如從一個目錄加載所有配置文件,Spring可能內部使用迭代器模式來遍歷這些資源。
- Spring提供了對資源的抽象,比如
- Bean的后處理器:
- 在Spring的應用上下文中,可能會有多個
BeanPostProcessor
實例。在初始化bean的過程中,Spring容器會遍歷這些后處理器,并對bean應用它們。這種遍歷的邏輯類似于迭代器模式。
- 在Spring的應用上下文中,可能會有多個
- 數據訪問模塊:
- 在Spring的數據訪問模塊,如JDBC或JPA集成中,處理查詢結果集時可能會隱式使用迭代器模式。例如,
JdbcTemplate
可能使用迭代器來遍歷ResultSet
。
- 在Spring的數據訪問模塊,如JDBC或JPA集成中,處理查詢結果集時可能會隱式使用迭代器模式。例如,
- Spring Batch:
- 在Spring Batch框架中,對于批量數據處理,迭代器模式可能被用于逐條處理大量記錄。
雖然這些例子并非迭代器模式的直接實現,但它們在設計上采用了迭代器模式的核心思想——通過迭代器來抽象和簡化對集合或序列的訪問。這種設計使得Spring的各個組件能夠以統一和靈活的方式處理集合和序列數據,同時保持了代碼的清晰性和可維護性。