軟體設計模式學習(二十)迭代器模式
阿新 • • 發佈:2020-05-25
> 迭代器模式是一種使用頻率非常高的設計模式,迭代器用於對一個聚合物件進行遍歷。通過引入迭代器可以將資料的遍歷功能從聚合物件中分離出來,聚合物件只負責儲存資料,聚合物件只負責儲存資料,而遍歷資料由迭代器來完成。
## 模式動機 一個聚合物件,如一個列表(List)或者一個集合(Set),應該提供一種方法來讓別人可以訪問它的元素,而又不需要暴露它的內部結構。此外,針對不同的需要,可能還要以不同方式遍歷整個聚合物件,但是我們不希在聚合物件的抽象層介面中充斥著各種不同遍歷的操作。怎樣遍歷一個聚合物件,又不需要了解聚合物件的內部結構,還能提供多種不同的遍歷方式,這就是迭代器模式所要解決的問題。 迭代器模式中,提供一個外部的迭代器來對聚合物件進行訪問和遍歷,迭代器定義一個訪問該聚合元素的介面,並且可以跟蹤當前遍歷物件,瞭解哪些元素已經遍歷過而哪些沒有。
## 模式結構 ![](https://img2020.cnblogs.com/blog/1759254/202005/1759254-20200525155540657-882390845.png) 1. Iterator(抽象迭代器) 抽象迭代器定義了訪問和遍歷元素的介面,一般宣告以下方法: - 用於獲取第一個元素的 first() - 用於訪問下一個元素的 next() - 用於判斷是否還有下一個元素的 hasNext() - 用於獲取當前元素的 currentItem() 2. ConcreteIterator(具體迭代器) 具體迭代器實現了抽象迭代器介面,完成對聚合物件的遍歷,同時在對聚合進行遍歷時跟蹤其當前位置 3. Aggregate(抽象聚合類) 抽象聚合類用於儲存物件,並定義建立相應迭代器物件的介面,宣告一個 createIterator() 方法用於建立一個迭代器物件 4. ConcreteAggregate(具體聚合類) 具體聚合類實現了建立相應迭代器的介面,實現了在聚合類中宣告的 createIterator() 方法,該方法返回一個與具體聚合對應的具體迭代器 ConcreteIterator 例項
## 模式適用環境 在以下情況可以使用迭代器模式: 1. 訪問一個聚合物件的內容而無須暴露它的內部表示 2. 需要為聚合物件提供多種遍歷方式 3. 為遍歷不同的聚合結構提供一個統一的介面
## Java 迭代器 Java 中的集合框架 Collections,其基本介面層次結構如圖 ![](https://img2020.cnblogs.com/blog/1759254/202005/1759254-20200525155620746-938469662.png) Collection 是所有集合類的根介面,它的主要方法如下: ```java boolean add(Object c); boolean addAll(Collection c); boolean remove(Object o); boolean removeAll(Collection c); boolean remainAll(Collection c); Iterator iterator(); ``` Collection 的 iterator() 方法返回一個 java.util.Iterator 型別的物件,而其子介面 java.util.List 的 listIterator() 方法返回一個 java.util.ListIterator 型別的物件,ListIterator 是 Iterator 的子類,它們構成了 Java 語言對迭代器模式的支援。 在 JDK 中,Iterator 介面具有如下三個基本方法: 1. Object next():通過反覆呼叫 next() 方法可以逐個訪問聚合中的元素 2. boolean hasNext():用於判斷聚合物件在是否還存在下一個元素,為了不丟擲異常,必須在呼叫 next() 之前先呼叫 hasNext()。如果迭代物件仍然擁有可供訪問的元素,那麼 hasNext() 返回 true 3. void remove():刪除上一次呼叫 next() 時返回的元素 Java 迭代器可以理解為它工作時在聚合物件的各個元素之間,每呼叫一次 next() 方法,迭代器便越過下個元素,並且返回它剛越過的那個元素的地址引用。 ![](https://img2020.cnblogs.com/blog/1759254/202005/1759254-20200525155644118-1997753286.png) 在第一個 next() 方法被呼叫時,迭代器由“元素1”與“元素2”之間移動至“元素2”與“元素3”之間,跨越了“元素2”,因此 next() 方法將返回對“元素2”的引用;在第二個 next() 方法被呼叫時,迭代器由“元素2”與“元素3”之間移至“元素3”與“元素4”之間,next() 方法將返回對“元素3”的引用,此時呼叫 remove() 方法,則可將”元素3“刪除。 需要注意的是,next() 方法與 remove() 方法的呼叫是相互關聯的。如果呼叫 remove() 之前沒有先對 next() 進行呼叫,那麼將丟擲異常,因為沒有任何可供刪除的元