折騰Java設計模式之迭代器模式
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
提供一種不公示其底層細節(結構)的情況下能順序訪問聚合物件元素的方法。
其實在java體系中,jdk已經引入了迭代器介面以及對於的容器介面等。就拿迭代器中的角色,在java中找出其對應的類。
具體角色
(1)迭代器角色(Iterator):定義遍歷元素所需要的方法,一般來說會有這麼三個方法:取得下一個元素的方法next(),判斷是否遍歷結束的方法hasNext()),移出當前物件的方法remove(), (2)具體迭代器角色(Concrete Iterator):實現迭代器介面中定義的方法,完成集合的迭代。 (3)容器角色(Aggregate): 一般是一個介面,提供一個iterator()方法,例如java中的Collection介面,List介面,Set介面等 (4)具體容器角色(ConcreteAggregate):就是抽象容器的具體實現類,比如List介面的有序列表實現ArrayList,List介面的連結串列實現LinkList,Set介面的雜湊列表的實現HashSet等。
單獨舉出ArrayList的角色,
迭代器角色對應java中的java.lang.Iterator,這個迭代器是java容器公用的。
容器角色對應java.lang.Iterable,其還有Iterator iterator()方法獲取迭代器。
具體迭代器角色對應java.lang.ArrayList.Itr,實現了對應的hasNext、next、remove方法。
具體容器角色那就是java.lang.ArrayList了,實現iterator方法返回Itr具體迭代器,用遊標形式實現。
再看看UML類

專案例項
專案中很簡單的實現了一個容器和迭代器。大致參考了ArrayList實現,但是是簡潔版本,去除很多無關以及效能上的東西,只保留最基本的迭代器元素。
@Slf4j public class Application { public static void main(String[] args) { Aggregate<Integer> aggregate = new ConcreteAggregate<>(); aggregate.add(1); aggregate.add(2); aggregate.add(3); aggregate.add(4); Iterator<Integer> iterator = aggregate.iterator(); while (iterator.hasNext()) { log.info("迴圈資料{}", iterator.next()); } } } 複製程式碼
執行結果如下

簡單的迭代器定義
public interface Iterator<E> { boolean hasNext(); E next(); } 複製程式碼
簡單容器定義
public interface Aggregate<T> { Iterator<T> iterator(); void add(T t); } 複製程式碼
具體容器和具體的迭代器定義
public class ConcreteAggregate<E> implements Aggregate<E> { private Object[] elements; private int size = 0; public ConcreteAggregate() { elements = new Object[16]; } public int getSize() { return size; } public void add(E e) { elements[size++] = e; } @Override public Iterator<E> iterator() { return new ConcreteIterator<E>(); } private class ConcreteIterator<E> implements Iterator<E> { int cursor; @Override public boolean hasNext() { return cursor != size; } @Override public E next() { if (cursor >= size) { return null; } return (E) elements[cursor++]; } } } 複製程式碼
具體容器中用陣列來作為容器來儲存元素,而且最簡單的容器,固定了大小,並沒有實現擴容的演算法等等,只是一個簡單的樣例,但是大部分上,都是直接使用java帶有的迭代器。
優點
- 簡化了遍歷方式,對於物件集合的遍歷,還是比較麻煩的,對於陣列或者有序列表,我們尚可以通過遊標來取得,但使用者需要在對集合瞭解很清楚的前提下,自行遍歷物件,但是對於hash表來說,使用者遍歷起來就比較麻煩了。而引入了迭代器方法後,使用者用起來就簡單的多了。
- 可以提供多種遍歷方式,比如說對有序列表,我們可以根據需要提供正序遍歷,倒序遍歷兩種迭代器,使用者用起來只需要得到我們實現好的迭代器,就可以方便的對集合進行遍歷了。
- 封裝性良好,使用者只需要得到迭代器就可以遍歷,而對於遍歷演算法則不用去關心。
缺點
由於迭代器模式將儲存資料和遍歷資料的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
對於比較簡單的遍歷(像陣列或者有序列表),使用迭代器方式遍歷較為繁瑣,大家可能都有感覺,像ArrayList,我們寧可願意使用for迴圈和get方法來遍歷集合。
總結
迭代器模式是與集合共生共死的,一般來說,我們只要實現一個集合,就需要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有自己的迭代器。假如我們要實現一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現一個迭代器。