天天看點

設計模式-01 疊代器模式

目錄

設計模式-01 疊代器模式

簡介

例子

類圖

代碼

分析特點

總結

通用結構

屏蔽實作

降低耦合

靈活疊代

Iterator 中文對應疊代器,用于在資料集合中按照順序周遊集合。

舉一個最基本的周遊數組的例子:

類中的 iterate 方法非常完美地解決了周遊的任務,小巧精幹。

但是:

它的實作決定了它隻能周遊數組。

暴露細節過多,如果要更改資料存儲結構(arr 改成 List 類型了),則需要修改而不是添加代碼,違反 OCP 原則。

這個方法告訴和保證給調用者的細節過多(資料存儲類型),不符合面向抽象而非具體程式設計的原則。

……

為了解決這些問題,我們引入 Iterator 模式。

設計模式-01 疊代器模式

Aggregate 接口規定了它的實作類必須具有傳回一個 Iterator 的方法,也就是說它的實作者能生成疊代器進行疊代。

Iterator 接口規定了它的實作類必須要有 next 和 hasNext 兩個方法,也就是說,所有的疊代器必須要實作這兩個功能。

BookShelfIterator 類實作了 Iterator 接口,表明它是一個疊代器,而且專門疊代 BookShelf。

BookShelf 類實作了 Aggregate 接口,是以它把自己作為參數,初始化傳回了 BookShelfIterator 。

Client 要想周遊 BookShelf,隻需要調用後者的 iterator 方法,獲得 BookShef 的疊代器,然後使用疊代器進行疊代。不止對 BookShelf 這樣進行疊代操作,使用者對凡是實作了 Aggregate 接口的集合進行疊代,都是如此。在這個過程中:

疊代的過程和具體方式對 Client 來說是未知的,Client 用一個 Iterator 引用的執行個體進行疊代,非常符合面向抽象(接口)的原則。

假如 BookShelf 改用 <code>ArrayList&lt;book&gt;</code>實作書本的存儲,隻需要增加一個新的、實作了 Iterator 接口的疊代器,并且在這個疊代器中編寫周遊 ArrayList 的具體實作,最後在 BookShelf 的 iterator方法中傳回新的疊代器即可,符合 OCP 原則。

Client 完全感覺不到資料存儲結構和周遊實作的改變,如果在新的疊代器實作中改成逆序疊代,Client 也隻會感覺到疊代出的元素順序發生了改變,完全不清楚具體的細節。

這是更為一般的疊代器模式:

設計模式-01 疊代器模式

回到一個設計模式共性的問題:為什麼這麼麻煩?既然是一個數組,直接周遊處理就是最好的操作,似乎根本沒有引入 Iterator 的必要。

核心問題:替換存儲結構而完全不影響程式的其它部分。

如果 BookShelf 改用 java.util.List 管理書本,Client 使用 Iterator 進行疊代的操作代碼不需要任何變動:

設計模式的作用之一就是幫助我們編寫可複用的類,而所謂的可複用就是當一個元件(類)發生變化時,不需要對其他元件進行改動,或者是進行很小的改動就能應對新的變化和需求。這也進一步解釋了,在 BookShelf 的 iterator 方法中傳回的是一個 Iterator 而不是 BookShelfIterator。

以往,我們更喜歡使用具體的類來解決具體的問題,這是一種務實的做法,但具體類的編寫往往會造成強的關聯和耦合,設計模式的任務之一,就是要降低元件或者說代碼之間的耦合。

一個 ConcreteAggregate 可以對應多個 ConcreteIterator,可以從前往後疊代,也可以從後往前疊代……