設計模式 (十一) 迭代器模式

介紹

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

定義

提供一種方法順序訪問一個容器對象中的各個元素,而又不須要暴露該對象的內部表示。java

使用場景

遍歷一個容器對象時。git

UML 類圖

hfDif.png

  • Iterator: 迭代器接口。迭代器接口負責定義、訪問和遍歷元素的接口。
  • Concrete Iterator: 具體迭代器類。具體迭代器類的目的主要是實現迭代器接口,並記錄遍歷的當前位置。
  • Aggregate: 容器接口。容器接口負責提供建立具體迭代器角色的接口。
  • Concrete Aggregate: 具體容器類。具體迭代器角色與該容器相關聯。
  • Client: 客戶類。

代碼示例

簡單示例

迭代器接口github

public interface Iterator<T> {

    /** * 是否還有下一個元素 * @return true 表示有,false 表示沒有 */
    boolean hasNext();

    /** * 返回當前位置的元素並將位置移動到下一位 * @return */
    T next();
}
複製代碼

具體迭代器類算法

public class ConcreteIterator<T> implements Iterator<T> {


    /** * 模擬用一個 List */
    private List<T> mList = new ArrayList<>();

    private int cursor = 0;


    public ConcreteIterator(List<T> list) {
        this.mList = list;
    }

    @Override
    public boolean hasNext() {
        return cursor != mList.size();
    }

    @Override
    public T next() {
        //定義一個臨時變量
        T obj = null;
        if (this.hasNext()) {
            obj = this.mList.get(cursor++);
        }
        return obj;
    }
}

複製代碼

容器接口設計模式

public interface Aggregate<T> {

    /** * 添加一個對象 * @param t */
    void add(T t);

    /** * 刪除的對象 * @param t */
    void remove(T t);

    /** * 獲取容器的迭代器 * @return */
    Iterator<T> iterator();

}
複製代碼

具體容器類數組

public class ConcreteAggregate<T> implements Aggregate<T>{

    /** * 模擬具體容器 */
    private List<T> mLists = new ArrayList<>();

    @Override
    public void add(T t) {
        mLists.add(t);
    }

    @Override
    public void remove(T t) {
        mLists.remove(t);

    }

    @Override
    public Iterator<T> iterator() {
        return new ConcreteIterator<T>(mLists);
    }
}
複製代碼

客戶類ide

@Test
    public void testIterators() {
        //建立容器
        Aggregate<String> aggregate = new ConcreteAggregate<>();
        aggregate.add("1");
        aggregate.add("2");
        aggregate.add("3");
        aggregate.add("4");

        //拿到容器迭代器,使用迭代器遍歷
        Iterator<String> iterator = aggregate.iterator();
        while (iterator.hasNext()) {
            System.out.println("Aggregate: " + iterator.next());
        }

    }
複製代碼

Output:this

Aggregate: 1
Aggregate: 2
Aggregate: 3
Aggregate: 4 
複製代碼

總結

對於迭代器模式來講,其自身優勢很明顯也很單一,支持以不一樣的方式去遍歷一個容器對象,也能夠有多個遍歷,弱化了容器類與遍歷算法之間的關係,其缺點就是對類文件的增長。spa

你們也可能會想到其餘語言,如 C++、Python 、PHP 等,他們內部也有衆多容器體的定義,固然,也有相應的迭代器。迭代器模式發展至今,幾乎每一種高級語言都有相應的內置實現,對於開發者而言,已經極少會去本身實現迭代器了,所以,對於迭代器模式在於瞭解而非應用。

文章代碼地址

特別感謝

《 Android 源碼設計模式解析與實戰 》

感謝你的閱讀,謝謝!

相關文章
相關標籤/搜索