迭代器模式是一種使用頻率很是高的設計模式,迭代器用於對一個聚合對象進行遍歷。經過引入迭代器能夠將數據的遍歷功能從聚合對象中分離出來,聚合對象只負責存儲數據,聚合對象只負責存儲數據,而遍歷數據由迭代器來完成。java
一個聚合對象,如一個列表(List)或者一個集合(Set),應該提供一種方法來讓別人能夠訪問它的元素,而又不須要暴露它的內部結構。此外,針對不一樣的須要,可能還要以不一樣方式遍歷整個聚合對象,可是咱們不希在聚合對象的抽象層接口中充斥着各類不一樣遍歷的操做。怎樣遍歷一個聚合對象,又不須要了解聚合對象的內部結構,還能提供多種不一樣的遍歷方式,這就是迭代器模式所要解決的問題。算法
迭代器模式中,提供一個外部的迭代器來對聚合對象進行訪問和遍歷,迭代器定義一個訪問該聚合元素的接口,而且能夠跟蹤當前遍歷對象,瞭解哪些元素已經遍歷過而哪些沒有。設計模式
提供一種方法來訪問聚合對象,而不用暴露這個對象的內部表示,其別名爲遊標(Cursor)。迭代器模式是一種對象行爲模式。數組
Iterator(抽象迭代器)框架
抽象迭代器定義了訪問和遍歷元素的接口,通常聲明如下方法:this
ConcreteIterator(具體迭代器)設計
具體迭代器實現了抽象迭代器接口,完成對聚合對象的遍歷,同時在對聚合進行遍歷時跟蹤其當前位置code
Aggregate(抽象聚合類)對象
抽象聚合類用於存儲對象,並定義建立相應迭代器對象的接口,聲明一個 createIterator() 方法用於建立一個迭代器對象blog
ConcreteAggregate(具體聚合類)
具體聚合類實現了建立相應迭代器的接口,實現了在聚合類中聲明的 createIterator() 方法,該方法返回一個與具體聚合對應的具體迭代器 ConcreteIterator 實例
存儲數據是聚合對象的最基本職責,其中包含存儲數據的類型、存儲空間的大小、存儲空間的分配,以及存儲的方式和順序。然而,聚合對象除了能存儲數據外,還必須提供遍歷訪問其內部數據的方式,同時這些遍歷方式可能會根據不一樣的情形提供不一樣的實現。
所以,聚合對象主要有兩個職責:一是存儲內部數據;二是遍歷內部數據。前者是聚合對象的基本功能,後者是能夠分離的。根據單一職責原則,對象承擔的職責越少,對象的穩定性就越好,咱們將遍歷聚合對象中數據的行爲提取出來,封裝到一個迭代器中,經過專門的迭代器來遍歷聚合對象的內部數據。迭代器模式是單一職責原則的完美體現。
下面經過一個簡單的自定義迭代器來分析迭代器模式的結構
首先定義一個簡單的迭代器去接口
public interface MyIterator { void first(); // 訪問第一個元素 void next(); // 訪問下一個元素 boolean isLast(); // 判斷是不是最後一個元素 Object currentItem(); // 獲取當前元素 }
而後須要定義一個聚合接口
public interface MyCollection { // 返回一個 MyIterator 迭代器對象 MyIterator createIterator(); }
定義好抽象層以後,咱們須要定義抽象迭代器接口和抽象聚合接口的實現類,通常將具體迭代器類做爲具體聚合類的內部類,從而迭代器能夠實現直接訪問聚合類中的數據
public class NewCollection implements MyCollection { private Object[] obj = {"dog", "pig", "cat", "monkey", "pig"}; public MyIterator createIterator() { return new NewIterator(); } private class NewIterator implements MyIterator { private int currentIndex = 0; public void first() { currentIndex = 0; } public void next() { if(currentIndex < obj.length) { currentIndex++; } } public boolean isLast() { return currentIndex == obj.length; } public void currentItem() { return obj[currentIndex]; } } }
NewCollection 類實現了 MyCollection 接口,實現了 createIterator() 方法,同時定義了一個數組用於存儲數據元素,還定義了一個實現了 MyIterator 接口的內部類,索引變量 currentIndex 用於保存所操做的數組元素的下標值。客戶端代碼以下:
public class Client { public static void process(MyCollection collection) { MyIterator i = collection.createIterator(); while(!i.isLast()) { System.out.println(i.currentItem().toString()); i.next(); } } public static void main(String args[]) { MyCollection collection = new NewCollection(); process(collection); } }
除了使用內部類實現以外,也可使用常規的方式來實現迭代器
public class ConcreteIterator implements Iterator { private ConcreteAggregate objects; public ConcreteIterator(ConcreteAggregate objects) { this.objects = objects; } public void first() { ... } public void next() { ... } public boolean isLast() { ... } public void currentItem() { ... } } public class ConcreteAggregate implements Aggregate { ... public Iterator createIterator() { return new ConcreteIterator(this); } }
迭代器模式中應用了工廠方法模式,聚合類充當工廠類,而迭代器充當產品類
迭代器模式優勢:
迭代器模式缺點:
在如下狀況可使用迭代器模式:
Java 中的集合框架 Collections,其基本接口層次結構如圖
Collection 是全部集合類的根接口,它的主要方法以下:
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 接口具備以下三個基本方法:
Java 迭代器能夠理解爲它工做時在聚合對象的各個元素之間,每調用一次 next() 方法,迭代器便越過下個元素,而且返回它剛越過的那個元素的地址引用。
在第一個 next() 方法被調用時,迭代器由「元素1」與「元素2」之間移動至「元素2」與「元素3」之間,跨越了「元素2」,所以 next() 方法將返回對「元素2」的引用;在第二個 next() 方法被調用時,迭代器由「元素2」與「元素3」之間移至「元素3」與「元素4」之間,next() 方法將返回對「元素3」的引用,此時調用 remove() 方法,則可將」元素3「刪除。
須要注意的是,next() 方法與 remove() 方法的調用是相互關聯的。若是調用 remove() 以前沒有先對 next() 進行調用,那麼將拋出異常,由於沒有任何可供刪除的元素