折騰Java設計模式之迭代器模式

迭代器模式

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.html

提供一種不公示其底層細節(結構)的狀況下能順序訪問聚合對象元素的方法。java

其實在java體系中,jdk已經引入了迭代器接口以及對於的容器接口等。就拿迭代器中的角色,在java中找出其對應的類。git

具體角色

(1)迭代器角色(Iterator):定義遍歷元素所須要的方法,通常來講會有這麼三個方法:取得下一個元素的方法next(),判斷是否遍歷結束的方法hasNext()),移出當前對象的方法remove(),github

(2)具體迭代器角色(Concrete Iterator):實現迭代器接口中定義的方法,完成集合的迭代。算法

(3)容器角色(Aggregate): 通常是一個接口,提供一個iterator()方法,例如java中的Collection接口,List接口,Set接口等設計模式

(4)具體容器角色(ConcreteAggregate):就是抽象容器的具體實現類,好比List接口的有序列表實現ArrayList,List接口的鏈表實現LinkList,Set接口的哈希列表的實現HashSet等。數組

單獨舉出ArrayList的角色,ide

迭代器角色對應java中的java.lang.Iterator,這個迭代器是java容器公用的。性能

容器角色對應java.lang.Iterable,其還有Iterator<T> iterator()方法獲取迭代器。設計

具體迭代器角色對應java.lang.ArrayList.Itr,實現了對應的hasNext、next、remove方法。

具體容器角色那就是java.lang.ArrayList了,實現iterator方法返回Itr具體迭代器,用遊標形式實現。

再看看UML類

img

項目實例

源碼在Github

項目中很簡單的實現了一個容器和迭代器。大體參考了ArrayList實現,可是是簡潔版本,去除不少無關以及性能上的東西,只保留最基本的迭代器元素。

@Slf4j
public class Application {

    public static void main(String[] args) {
        Aggregate<Integer> aggregate = new ConcreteAggregate<>();
        aggregate.add(1);
        aggregate.add(2);
        aggregate.add(3);
        aggregate.add(4);

        Iterator<Integer> iterator = aggregate.iterator();
        while (iterator.hasNext()) {
            log.info("循環數據{}", iterator.next());
        }
    }
}

執行結果以下

image-20190102175121620

簡單的迭代器定義

public interface Iterator<E> {

    boolean hasNext();

    E next();

}

簡單容器定義

public interface Aggregate<T> {

    Iterator<T> iterator();

    void add(T t);

}

具體容器和具體的迭代器定義

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

    private Object[] elements;

    private int size = 0;

    public ConcreteAggregate() {
        elements = new Object[16];
    }

    public int getSize() {
        return size;
    }

    public void add(E e) {
        elements[size++] = e;
    }

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

    private class ConcreteIterator<E> implements Iterator<E> {

        int cursor;

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

        @Override
        public E next() {
            if (cursor >= size) {
                return null;
            }
            return (E) elements[cursor++];
        }

    }
}

具體容器中用數組來做爲容器來存儲元素,並且最簡單的容器,固定了大小,並無實現擴容的算法等等,只是一個簡單的樣例,可是大部分上,都是直接使用java帶有的迭代器。

優勢

  • 簡化了遍歷方式,對於對象集合的遍歷,仍是比較麻煩的,對於數組或者有序列表,咱們尚能夠經過遊標來取得,但用戶須要在對集合瞭解很清楚的前提下,自行遍歷對象,可是對於hash表來講,用戶遍歷起來就比較麻煩了。而引入了迭代器方法後,用戶用起來就簡單的多了。
  • 能夠提供多種遍歷方式,好比說對有序列表,咱們能夠根據須要提供正序遍歷,倒序遍歷兩種迭代器,用戶用起來只須要獲得咱們實現好的迭代器,就能夠方便的對集合進行遍歷了。
  • 封裝性良好,用戶只須要獲得迭代器就能夠遍歷,而對於遍歷算法則不用去關心。

缺點

因爲迭代器模式將存儲數據和遍歷數據的職責分離,增長新的聚合類須要對應增長新的迭代器類,類的個數成對增長,這在必定程度上增長了系統的複雜性。

對於比較簡單的遍歷(像數組或者有序列表),使用迭代器方式遍歷較爲繁瑣,你們可能都有感受,像ArrayList,咱們寧肯願意使用for循環和get方法來遍歷集合。

總結

迭代器模式是與集合共生共死的,通常來講,咱們只要實現一個集合,就須要同時提供這個集合的迭代器,就像java中的Collection,List、Set、Map等,這些集合都有本身的迭代器。假如咱們要實現一個這樣的新的容器,固然也須要引入迭代器模式,給咱們的容器實現一個迭代器。

參考

wiki的迭代器模式

迭代器模式|菜鳥教程

Java設計模式系列之迭代器模式

歡迎關注

微

相關文章
相關標籤/搜索