1. 程式人生 > >java/android 設計模式學習筆記(20)---迭代器模式

java/android 設計模式學習筆記(20)---迭代器模式

  我們這篇部落格來介紹一下迭代器模式(Iterator Pattern),又稱為遊標(Cursor Pattern)模式,是行為型設計模式之一。迭代器模式算是一個比較古老的設計模式,其源於對容器的訪問,比如 Java 中的 List、Map、陣列等,我們知道對容器物件的訪問必然會涉及遍歷演算法,我們可以將遍歷的方法封裝在容器中,或者不提供遍歷方法。如果我們將遍歷的方法封裝到容器中,那麼對於容器類來說就承擔了過多的功能,容器類不僅要維護自身內部的資料元素而且還要對外提供遍歷的介面方法,因為遍歷狀態的儲存問題還不能對同一個容器同時進行多個遍歷操作,如果我們不提供遍歷方法而讓使用者自己去實現,又會讓容器的內部細節暴露無遺,正因於此,迭代模式應運而生,在客戶訪問類與容器體之間插入一個第三者——迭代器,很好地解決了上面所述的弊端。
  轉載請註明出處:

http://blog.csdn.net/self_study/article/details/52502709
  PS:對技術感興趣的同鞋加群544645972一起交流。

設計模式總目錄

特點

  提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部的表示。
  迭代器模式讓我們能遊走於聚合內的每一個元素,而又不暴露其內部的表示,把遊走的任務放在迭代器上,而不是聚合上。這樣簡化了聚合的介面和實現,也讓責任各得其所。
  迭代器模式使用的場景也很簡單:遍歷一個容器物件時。

UML類圖

  這裡寫圖片描述
迭代器模式角色:

  • Iterator:迭代器介面
  • 迭代器介面負責定義、訪問和遍歷元素的介面。
  • ConcreteIterator:具體迭代器類
  • 具體迭代器類的目的主要是實現迭代器介面,並記錄遍歷的當前位置。
  • Aggregate:容器介面
  • 容器介面負責提供建立具體迭代器角色的介面。
  • ConcreteAggregate:具體容器類
  • 具體迭代器角色與該容器相關聯。
  • Client:客戶類
  據此我們可以寫出迭代器模式的通用程式碼:
迭代器類:
Iterator.class
public interface Iterator<T> {
    boolean hasNext();

    T next();
}

ConcreteIterator.class

public class ConcreteIterator<T
> implements Iterator<T>{
private List<T> list; private int cursor = 0; public ConcreteIterator(List<T> list) { this.list = list; } @Override public boolean hasNext() { return cursor != list.size(); } @Override public T next() { T obj = null; if (this.hasNext()) { obj = this.list.get(cursor++); } return obj; } }

容器類:
Aggregation.class

public interface Aggregation<T> {

    void add(T obj);

    void remove(T obj);

    Iterator<T> iterator();
}

ConcreteAggregation.class

public class ConcreteAggregation<T> implements Aggregation<T>{
    private List<T> list = new ArrayList<>();

    @Override
    public void add(T obj) {
        list.add(obj);
    }

    @Override
    public void remove(T obj) {
        list.remove(obj);
    }

    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<>(list);
    }
}

客戶端程式碼

public class Client {
    public static void main(String args[]) {
        Aggregation<String> a = new ConcreteAggregation<>();
        a.add("a");
        a.add("b");
        a.add("c");
        Iterator<String> iterator = a.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());
        }
    }
}

最後結果就是遍歷了一遍:

abc
Process finished with exit code 0

示例與原始碼

  迭代器這個模式對於很多開發者來說幾乎不會自己去實現一個迭代器,但是我們平時使用的頻率不會低,在 Android 中,除了各種資料結構體,如 List、Map 等所包含的迭代器外,資料庫查詢的 Cursor 也是一個迭代器。
  我們這裡就簡單分析一下 ArrayList 的 Iterator 原始碼:
Iterator.class

public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();

    /**
     * Removes from the underlying collection the last element returned
     * by this iterator (optional operation).  This method can be called
     * only once per call to {@link #next}.  The behavior of an iterator
     * is unspecified if the underlying collection is modified while the
     * iteration is in progress in any way other than by calling this
     * method.
     *
     * @throws UnsupportedOperationException if the {@code remove}
     *         operation is not supported by this iterator
     *
     * @throws IllegalStateException if the {@code next} method has not
     *         yet been called, or the {@code remove} method has already
     *         been called after the last call to the {@code next}
     *         method
     */
    void remove();
}

ArrayList.Itr.class

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

這就是 ArrayList 迭代器的具體實現,從原始碼中我們可以看到有一個 checkForComodification() 函式,丟擲的異常 ConcurrentModificationException 應該很多人認識,如果 modCount 不等於 expectedModCount,則丟擲 ConcurrentModificationException 異常,一般情況下出現在遍歷的同時呼叫了 ArrayList.remove 等操作對資料集合進行了更改,例如多執行緒中當一個執行緒刪除了元素,由於 modCount 是 AbstarctList 的成員變數,因此可能會導致在其他執行緒中modCount 和 expectedModCount 值不等。

總結

  對於迭代模式來說,其自身優點很明顯:

  • 迭代子模式簡化了聚集的介面,迭代子具備了一個遍歷介面,這樣聚集的介面就不必具備遍歷介面;
  • 每一個聚集物件都可以有一個或多個迭代子物件,每一個迭代子的迭代狀態可以是彼此獨立的。因此,一個聚集物件可以同時有幾個迭代在進行之中;
  • 由於遍歷演算法被封裝在迭代子角色裡面,因此迭代的演算法可以獨立於聚集角色變化。
而其缺點就是對類檔案的增加。其實迭代模式發展至今,幾乎每一種高階語言都有相應的內建實現,對於開發者來說,已經很少會去由自己來實現迭代器了,因此,對於迭代器模式我們更多地是在於瞭解而非應用。

原始碼下載

引用

相關推薦

java/android 設計模式學習筆記20---模式

  我們這篇部落格來介紹一下迭代器模式(Iterator Pattern),又稱為遊標(Cursor Pattern)模式,是行為型設計模式之一。迭代器模式算是一個比較古老的設計模式,其源於對容器的訪問,比如 Java 中的 List、Map、陣列等,我們知道對

C++學習筆記5

迭代器:設計了一個統一的遍歷容器的方式。 這種設計模式叫做迭代器模式。 容器中對資料結構進行了一個封裝,要想遍歷整個資料元素, 用普通指標是無法訪問容器的資料結構。 所以需要設計一個面向物件的指標來訪問。 可以讓容器中提供begin()和end()這個介面,用

設計模式學習筆記3:觀察者模式2

       上一篇的觀察者模式的筆記中提到的例子,只是Subject把自身狀態“推”給Observer的方式。 //通知觀察者資訊發生改變了 @Override public void notifyObservers() { for (

Java程式設計師從笨鳥到菜鳥之四十五大話設計模式模式和命令模式

歡迎關注微信賬號:java那些事:csh624366188.每天一篇java相關的文章 java交流工作群1: 77800592(已滿) java交流學生群2:234897635(已滿) java交流工作群3:94507287 java交流工作群4: 272265434 我的郵箱:

常用軟體設計模式模式

迭代器模式不常用,很多高階語言都將該模式封裝在語言中了,入C#的 foreach in 但是有必要了解一下 迭代器模式:提供一個方法順序訪問一個聚合物件中各個元素,而又不暴露該物件的內部表示。 優點: 1、它支援以不同的方式遍歷一個聚合物件。     &nb

python3語言學習筆記四:與生成器

迭代器(iterator)------一種物件 迭代是Python最強大的功能之一,是訪問集合元素的一種方式。 迭代器是一個可以記住遍歷的位置的物件。 迭代器物件從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。 迭代器有兩個基本的方法:iter() 和

設計模式—— 模式

一、含義 提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部的表示。當我們在專案中需要遍歷不同的集合、陣列時,可以考慮使用迭代器模式,提供一個統一的遍歷方法。 二、要點 1.迭代器將遍歷聚合的工作封裝進一個物件中。 2.迭代器提供一個通用的介面,讓我們遍歷聚合的項,當我們

設計模式系列十三模式(Iterator Pattern)

// 迭代器模式 // IteratorPattern.h檔案 #ifndef ITERATOR #define ITERATOR #include <iostream> #include <iomanip> #include <string> #include <

設計模式10 模式--行為型

定義 迭代器模式(Iterator Pattern):提供一種方法來訪問聚合物件,而不用暴露這個物件的內部表示。 角色 抽象迭代器(Iterator) 抽象迭代器定義了訪問和遍歷元素的介面,一般宣告如下方法:用於獲取第一個元素的first(),用

java/android 設計模式學習筆記10---建造者模式

  這篇部落格我們來介紹一下建造者模式(Builder Pattern),建造者模式又被稱為生成器模式,是創造性模式之一,與工廠方法模式和抽象工廠模式不同,後兩者的目的是為了實現多型性,而 Builder 模式的目的則是為了將物件的構建與展示分離。Builder

java/android 設計模式學習筆記15---責任鏈模式

  這篇部落格我們來介紹一下責任鏈模式(Chain-of-responsibility Pattern),責任聯模式又稱為職責鏈模式,是行為型設計模式之一。顧名思義,責任鏈模式中存在一個鏈式結構,多個節點首尾相連,每個節點都可以被拆開再連線,因此,鏈式結構具有很

java/android 設計模式學習筆記12---組合模式

  這篇我們來介紹一下組合模式(Composite Pattern),它也稱為部分整體模式(Part-Whole Pattern),結構型模式之一。組合模式比較簡單,它將一組相似的物件看作一個物件處理,並根據一個樹狀結構來組合物件,然後提供一個統一的方法去訪問相

java設計模式學習筆記 --- 行為型模式

文章目錄 責任鏈模式 策略模式 命令模式 直譯器模式 迭代器模式 中介者模式 備忘錄模式 觀察者模式 狀態模式 模板方法模式 訪問者模式 責任鏈模式 我獲取了一個物件,現在需要根據物件

java設計模式學習筆記--- 結構型模式

文章目錄 介面卡模式 組合模式 裝飾模式 代理模式 什麼時候使用代理模式 享元模式 外觀模式(門面模式) 橋樑模式 介面卡模式 介面卡是一個介面轉換器,用於在接收不同的輸入時,得到一致

java設計模式學習筆記--- 建立型模式

文章目錄 簡介 設計模式所遵循的幾個原則 一、工廠方法模式 簡單工廠模式 工廠方法模式 抽象工廠模式 工廠模式小結 單例模式 單例模式小結 建造者模式

JAVA設計模式學習筆記

2018年11月03日 12:14:18 築夢^_^ 閱讀數:6 個人分類: JAVA

java 設計模式 學習筆記17 橋接模式

 橋接模式:           將抽象部分與它的實現部分分離,使他們多可以獨立的變化。抽象與實現分離,表示抽象類和他的派生類用來實現自己的物件。        在系統中,可能有多角度分類,每一種分類都有可能變化,這時就把這種多角度分離出來讓他們獨立變化,減少各個角度的耦合。

java 設計模式 學習筆記16 單例模式

單例模式:保證一個類僅有一個例項,並提供一個訪問其例項的一個全域性訪問點 根據單例模式的定義,寫一個單例模式的例子需要注意兩點: 1.例項有該類自己生成      為了防止客戶程式碼通過 new Singleton()來例項一個物件,需要將 Singleton的預設建構函式

設計模式學習筆記 設計基本原則之【單一職責原則】

code 分享 開發者 實際應用 需要 ret ext file類 tor 單一職責原則(SRP: Single Responsibility Principle) 名詞解釋: 1) 職責:是指類變化的原因。 2) 職責擴散:就是因為某種原因,職責P被分化為粒度更細的職責P

設計模式學習筆記--簡單工廠模式和工廠模式

bsp bubuko rac oid nds gen body () pri 老生長談的兩個設計模式了,這裏把這兩個設計模式對比著來總結一下。 什麽是簡單工廠模式? 簡單工廠模式:根據傳入工廠類的參數動態決定要創建哪一個產品類的實例。 UML圖如下(以實現一個計算器為例):