設計模式之迭代子模式

迭代子模式又叫遊標(Cursor)模式,是對象的行爲模式。html

迭代子模式的定義

迭代子模式能夠順序地訪問一個彙集中的元素而沒必要暴露彙集的內部表象。咱們常見的集合有不少種類,其頂層數據存儲和組織方式的不一樣致使了咱們在對數據進行遍歷的時候存在一些差別,迭代器模式就是經過實現某種統一的方式來實現對不一樣的集合的遍歷,同時又不暴露出其底層的數據存儲和組織方式。java

例如,若是沒有使用Iterator,遍歷一個數組的方法是使用索引:設計模式

for(int i=0; i<array.size(); i++) { 
	get(i)
} 
複製代碼

而訪問一個鏈表(LinkedList)又必須使用while循環:數組

while((e=e.next())!=null) { 
	 e.data()
} 
複製代碼

以上兩種方法客戶端都必須事先知道集合的內部結構,訪問代碼和集合自己是緊耦合,沒法將訪問邏輯從集合類和客戶端代碼中分離出來,每一種集合對應一種遍歷方法,客戶端代碼沒法複用。微信

更恐怖的是,若是之後須要把ArrayList更換爲LinkedList,則原來的客戶端代碼必須所有重寫。ide

爲解決以上問題,Iterator模式老是用同一種邏輯來遍歷集合:測試

for(Iterator it = yourCollection.iterater(); it.hasNext(); ) 
{ ... } 
複製代碼

客戶端自身不維護遍歷集合的"指針",全部的內部狀態(如當前元素位置,是否有下一個元素)都由Iterator來維護,而這個Iterator由集合類經過工廠方法生成,所以,它知道如何遍歷整個集合。客戶端從不直接和集合類打交道,它老是控制Iterator,向它發送"向前","向後","取當前元素"的命令,就能夠間接遍歷整個集合。this

迭代子模式的結構

迭代模式中有以下的角色: spa

iteratorconstruct
迭代子模式的結構

  • 迭代器角色(Iterator): 負責定義訪問和遍歷元素的接口。
  • 具體迭代器角色(Concrete Iterator):實現迭代器接口,並要記錄遍歷中的當前位置。
  • 容器角色(Container): 負責提供建立具體迭代器角色的接口。
  • 具體容器角色(Concrete Container):實現建立具體迭代器角色的接口, 這個具體迭代器角色與該容器的結構相關。

迭代子模式的實現

迭代器接口實現,定義了獲取第一個節點的方法,前一個節點和後一個節點,以及判斷是否有下一個節點。設計

public interface Iterator {
    public Object first();
    
    public Object previous();
    
    public Object next();

    public boolean hasNext();
}
複製代碼

具體實現迭代器,實現上述接口定義的方法。

public class MyIterator implements Iterator{
    private List<Object> list;
    private int index = 0;

    public MyIterator(List<Object> list) {
        this.list = list;
    }
    @Override
    public Object previous() {
        if((this.index - 1) < 0){
            return null;
        }else{
            return this.list.get(--index);
        }
        
    }

    @Override
    public Object next() {
        if((this.index + 1) >= this.list.size()){
            return null;
        }else{
            return this.list.get(++index);
        }
    }
    @Override
    public boolean hasNext() {
        if(this.index < (this.list.size() - 1)){
            return true;
        }
        return false;
    }

    @Override
    public Object first() {
        if(this.list.size() <= 0){
            return null;
        }else{
            return this.list.get(0);
        }
    }
}
複製代碼

容器定義,定義了兩個抽象方法,用來設置具體的迭代器實現以及注入容器中的元素。

public abstract class Container {

    public abstract Iterator iterator();
    
    public abstract void put(Object obj);
}
複製代碼

具體的容器類基於List,實現抽象方法。

public class MyContainer extends Container{
    private List<Object> list;
    
    public MyContainer() {
        this.list = new ArrayList<Object>();
    }
    @Override
    public void put(Object obj){
        this.list.add(obj);
    }
    @Override
    public Iterator iterator() {
        return new MyIterator(list);
    }
}
複製代碼

客戶端測試類。設置元素,並使用迭代器進行遍歷。

public class ClientTest {

	public static void main(String[] args) {

		//建立一個自定義容器,直接使用ArrayList的實現
		Container strContainer = new MyContainer();
		strContainer.put("001");
		strContainer.put("002");

		Iterator myIterator = strContainer.iterator();

		//使用迭代器遍歷
		System.out.println(myIterator.first());
		while (myIterator.hasNext()) {
			System.out.println(myIterator.next());
		}
	}
}
複製代碼

iterator
類圖

總結

Iterator模式是用於遍歷集合類的標準訪問方法。它能夠把訪問邏輯從不一樣類型的集合類中抽象出來,從而避免向客戶端暴露集合的內部結構。

適用場景:

  • 訪問一個聚合對象的內容而無須暴露它的內部表示。
  • 須要爲聚合對象提供多種遍歷方式。
  • 爲遍歷不一樣的聚合結構提供一個統一的接口。

優勢:

  • 它支持以不一樣的方式遍歷一個聚合對象。
  • 迭代器簡化了聚合類。在同一個聚合上能夠有多個遍歷。
  • 在迭代器模式中,增長新的聚合類和迭代器類都很方便,無須修改原有代碼。
  • 系統須要訪問一個聚合對象的內容而無需暴露它的內部表示。

缺點:

  • 因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。
  • 迭代器模式在遍歷的同時更改迭代器所在的集合結構會致使出現異常。因此使用foreach語句只能在對集合進行遍歷,不能在遍歷的同時更改集合中的元素。

訂閱最新文章,歡迎關注個人公衆號

微信公衆號

參考

  1. java設計模式----迭代子模式
  2. Head First設計模式之迭代器模式
相關文章
相關標籤/搜索