Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> java/android 設計模式學習筆記(20)---迭代器模式

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

編輯:關於Android編程

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

特點

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

UML類圖

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

IteratZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcqO6tfy0+sb3vdO/2rX8tPrG973Tv9q4utTwtqjS5aGit8POyrrNsenA+tSqy9i1xL3Tv9qho0NvbmNyZXRlSXRlcmF0b3Kjur7fzOW1/LT6xvfA4L7fzOW1/LT6xvfA4LXExL+1xNb30qrKx8q1z9a1/LT6xve907/ao6yyorzHwryx6cD6tcS1scewzrvWw6GjQWdncmVnYXRlo7rI3cb3vdO/2sjdxve907/auLrU8Mzhuam0tL2ovt/M5bX8tPrG973Hyau1xL3Tv9qho0NvbmNyZXRlQWdncmVnYXRlo7q+38zlyN3G98Dgvt/M5bX8tPrG973HyavT67jDyN3G98/gudjBqqGjQ2xpZW50o7q/zbunwOChoaGhvt20y87Sw8e/ydLU0LSz9rX8tPrG98Sjyr21xM2o08O0+sLro7o8YnIgLz4NCrX8tPrG98Dgo7o8YnIgLz4NCjxzdHJvbmc+SXRlcmF0b3IuY2xhc3M8L3N0cm9uZz4NCjxwPiZuYnNwOzwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> public interface Iterator { boolean hasNext(); T next(); }

ConcreteIterator.class

public class ConcreteIterator implements Iterator{
    private List list;
    private int cursor = 0;

    public ConcreteIterator(List 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 {

    void add(T obj);

    void remove(T obj);

    Iterator iterator();
}

ConcreteAggregation.class

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

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

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

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

客戶端代碼

public class Client {
    public static void main(String args[]) {
        Aggregation a = new ConcreteAggregation<>();
        a.add("a");
        a.add("b");
        a.add("c");
        Iterator 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 {
    /**
     * 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 {
    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 值不等。

總結

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

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

 

源碼下載

https://github.com/zhaozepeng/Design-Patterns/tree/master/IteratorPattern

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved