一、定義
迭代器(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足夠用了