迭代器模式
一、定義
迭代器(Iterator Pattern)模式的定義:又稱為游標模式(Cursor Pattern),它提供一個對象來順序訪問聚合對象中的一系列數據,而不暴露聚合對象的內部表示。迭代器模式可以為不同容器提供一致的遍歷行為,而不用關心容器內容元素組成 結構,迭代器模式是一種對象行為型模式 ;迭代器模式是通過將聚合對象的遍歷行為分離出來,抽象成迭代器類來實現的,其目的是在不暴露聚合對象的內部結構的情況下,讓外部程式碼透明地訪問聚合的內部數據。現在我們來分析其基本結構與實現方法。
迭代器模式主要包含以下角色。
- 抽象聚合(Aggregate)角色:定義存儲、添加、刪除聚合對象以及創建迭代器對象的介面。
- 具體聚合(ConcreteAggregate)角色:實現抽象聚合類,返回一個具體迭代器的實例。
- 抽象迭代器(Iterator)角色:定義訪問和遍歷聚合元素的介面,通常包含 hasNext()、first()、next() 等方法。
- 具體迭代器(Concretelterator)角色:實現抽象迭代器介面中所定義的方法,完成對聚合對象的遍歷,記錄遍歷的當前位置。
二、迭代器模式的案例
迭代器模式在我們生活中應用的得也比較廣泛,比如物流系統中的傳送帶,不管傳送的是什麼物品,都被打包成一個一個的箱子並且有一個統一的二維碼。這樣我們不需要關心箱子裡面是啥,我們在分發時只需要一個一個檢查發送的目的地即可。還有將書放到書架中,並將書名按順序顯示而不用關心書的內容。這樣說可能大家還是覺得應用場景比較模糊,那麼就這樣說他的主要應用場景有三大類:
1、訪問一個聚合對象的內容而無須暴露它的內部表示。
2、需要為聚合對象提供多種遍歷方式。
3、為遍歷不同的聚合結構提供一個統一的介面。
其實這種設計模式我們在日常開發中基本不會用到,除非需要訂製一個自己實現的數據結構對應的迭代器,否則,開源框架提供的 API 完全夠用。
/**抽象容器:Aggregate 介面 * 所要便利的集合的介面。實現了該介面的類將成為一個可以保存多個元素的集合,類似數組。 * Aggregate介面中聲明的方法為iterator,作用為生成一個用於遍歷的迭代器。 * @param <E> */ public interface Aggregate<E>{ boolean add(E element); boolean remove(E element); public abstract Iterator iterator(); }
/**抽象迭代器:Iterator 介面 *作用為遍歷集合中元素,相當於循環語句中的循環變數(for(int i =0 ;i<arr.lenth;i++), * 具體實現一個順序遍歷的迭代器。 * hasNext() 方法判斷是否存在下一個,next()方法獲取下一個元素。 * next方法在獲取元素的同時,要將計數器向下一個元素的計數加一。獲取的是當前元素,並指向下一個元素。 */ public interface Iterator { public abstract boolean hasNext(); public abstract Object next(); }
public class Book { private String name ; public Book(String name){ this.name=name; } public String getName(){ return name; } }
/** * 具體聚合(ConcreteAggregate) * 實現Aggregate介面。實現了Aggregate介面的iterator方法。 */ public class BookShelf implements Aggregate { private List<Book> books; public BookShelf() { this.books = new ArrayList<Book>(); } public Book getBookAt(int index) { return books.get(index); } @Override public boolean add(Object element) { books.add((Book) element); return true; } public int getLength() { return books.size(); } @Override public boolean remove(Object element) { return false; } /** * 方法返回了遍曆書架時要用的BookShelfIterator類作為書架的迭代器。當外部要遍曆書架時會調用該方法。 * @return */ @Override public Iterator iterator() { return new BookShelfIterator(this); } }
public class BookShelfIterator implements Iterator { private BookShelf bookShelf; private int index; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf = bookShelf; this.index = 0; } public boolean hasNext() { if (index < bookShelf.getLength()) { return true; } else { return false; } } public Object next() { Book book = bookShelf.getBookAt(index); index++; return book; } }
public class Test { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(); bookShelf.add(new Book("A")); bookShelf.add(new Book("B")); bookShelf.add(new Book("C")); bookShelf.add(new Book("D")); Iterator it = bookShelf.iterator(); while (it.hasNext()) { Book book = (Book) it.next(); System.out.println(book.getName()); } } }
Iterator模式中各角色的作用
Iterator(迭代器)
該角色責任定義按順序逐個遍曆元素的介面。程式中,由Iterator介面扮演,定義了hasNext和next兩個方法。
Concretelterator(具體的迭代器)
該角色負責實現Iterator角色所定義的介面.該角色包含了遍歷集合所必須的資訊。
Aggregate(集合)
該角色負責定義創建Iterator角色的介面。這個介面是一個方法會創建出一個,按照順序訪問保存在我內部元素的人。
ConcreteAggregate(具體集合)
該角色負責實現Aggregate角色所定義的介面。他會創建出具體的Iterator角色,也就是ConcreteIterator,也就是實例中的BookShelf。
三、總結
優點:
- 多態迭代:為不同的聚合結構提供一致的遍歷介面,即一個迭代介面可以訪問不同的集合對象;
- 簡化集合對象介面:迭代器模式將集合對象本身應該提供的元素迭代介面抽取到了迭代器中,使集合對象無須關心具體迭代行為;
- 元素迭代功能多樣化:每個集合對象都可以提供一個或多個不同的迭代器,使的同種元索聚合結構可以有不同的迭代行為;
- 解耦迭代與集合:迭代器模式封裝了具體的迭代演算法,迭代演算法的變化,不會影響到集合對象的架構
缺點:
- 對於比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較為繁瑣。
- 在日常開發當中,我們幾乎不會自己寫迭代器。除非我們需要訂製一個自己實現的數據結構對應的迭代器,不然常規的API足夠用了