天天看點

【設計模式】20.疊代器模式概述結構案例實作優缺點使用場景JDK源碼解析

概述

定義:

提供一個對象來順序通路聚合對象中的一系列資料,而不暴露聚合對象的内部表示。

結構

疊代器模式主要包含以下角色:

  • 抽象聚合(Aggregate)角色:定義存儲、添加、删除聚合元素以及建立疊代器對象的接口。
  • 具體聚合(ConcreteAggregate)角色:實作抽象聚合類,傳回一個具體疊代器的執行個體。
  • 抽象疊代器(Iterator)角色:定義通路和周遊聚合元素的接口,通常包含 hasNext()、next() 等方法。
  • 具體疊代器(Concretelterator)角色:實作抽象疊代器接口中所定義的方法,完成對聚合對象的周遊,記錄周遊的目前位置。

案例實作

【例】定義一個可以存儲學生對象的容器對象,将周遊該容器的功能交由疊代器實作,涉及到的類如下:

【設計模式】20.疊代器模式概述結構案例實作優缺點使用場景JDK源碼解析

代碼如下:

定義疊代器接口,聲明hasNext、next方法

public interface StudentIterator {
    boolean hasNext();
    Student next();
}
           

定義具體的疊代器類,重寫所有的抽象方法

public class StudentIteratorImpl implements StudentIterator {
    private List<Student> list;
    private int position = 0;

    public StudentIteratorImpl(List<Student> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return position < list.size();
    }

    @Override
    public Student next() {
        Student currentStudent = list.get(position);
        position ++;
        return currentStudent;
    }
}
           

定義抽象容器類,包含添加元素,删除元素,擷取疊代器對象的方法

public interface StudentAggregate {
    void addStudent(Student student);

    void removeStudent(Student student);

    StudentIterator getStudentIterator();
}
           

定義具體的容器類,重寫所有的方法

public class StudentAggregateImpl implements StudentAggregate {

    private List<Student> list = new ArrayList<Student>();  // 學生清單

    @Override
    public void addStudent(Student student) {
        this.list.add(student);
    }

    @Override
    public void removeStudent(Student student) {
        this.list.remove(student);
    }

    @Override
    public StudentIterator getStudentIterator() {
        return new StudentIteratorImpl(list);
    }
}
           

優缺點

1,優點:

  • 它支援以不同的方式周遊一個聚合對象,在同一個聚合對象上可以定義多種周遊方式。在疊代器模式中隻需要用一個不同的疊代器來替換原有疊代器即可改變周遊算法,我們也可以自己定義疊代器的子類以支援新的周遊方式。
  • 疊代器簡化了聚合類。由于引入了疊代器,在原有的聚合對象中不需要再自行提供資料周遊等方法,這樣可以簡化聚合類的設計。
  • 在疊代器模式中,由于引入了抽象層,增加新的聚合類和疊代器類都很友善,無須修改原有代碼,滿足 “開閉原則” 的要求。

2,缺點:

增加了類的個數,這在一定程度上增加了系統的複雜性。

使用場景

  • 當需要為聚合對象提供多種周遊方式時。
  • 當需要為周遊不同的聚合結構提供一個統一的接口時。
  • 當通路一個聚合對象的内容而無須暴露其内部細節的表示時。

JDK源碼解析

疊代器模式在JAVA的很多集合類中被廣泛應用,接下來看看JAVA源碼中是如何使用疊代器模式的。

List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator(); //list.iterator()方法傳回的肯定是Iterator接口的子實作類對象
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
           

看完這段代碼是不是很熟悉,與我們上面代碼基本類似。單列集合都使用到了疊代器,我們以ArrayList舉例來說明

  • List:抽象聚合類
  • ArrayList:具體的聚合類
  • Iterator:抽象疊代器
  • list.iterator():傳回的是實作了

    Iterator

    接口的具體疊代器對象

具體的來看看 ArrayList的代碼實作

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    public Iterator<E> iterator() {
        return new Itr();
    }
    
    private class Itr implements Iterator<E> {
        int cursor;       // 下一個要傳回元素的索引
        int lastRet = -1; // 上一個傳回元素的索引
        int expectedModCount = modCount;

        Itr() {}
		
        //判斷是否還有元素
        public boolean hasNext() {
            return cursor != size;
        }

        //擷取下一個元素
        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];
        }
        ...
}
           

這部分代碼還是比較簡單,大緻就是在

iterator

方法中傳回了一個執行個體化的

Iterator

對象。Itr是一個内部類,它實作了

Iterator

接口并重寫了其中的抽象方法。

注意:

​ 當我們在使用JAVA開發的時候,想使用疊代器模式的話,隻要讓我們自己定義的容器類實作

java.util.Iterable

并實作其中的iterator()方法使其傳回一個

java.util.Iterator

的實作類就可以了。

繼續閱讀