行為型模式——迭代器模式

迭代器模式定義

迭代器模式(Iterator),提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中的各種元素,而又不暴露該對(duì)象的內(nèi)部表示。
Java程序員在使用集合(collection)時(shí),并不需要關(guān)注其類型是數(shù)組、列表、集合(set)還是其他,有些人并不知道這些集合包其實(shí)是使用了迭代器模式來(lái)實(shí)現(xiàn)的。

目的

迭代器模式提供了一種順序遍歷聚合對(duì)象元素而不暴露其內(nèi)部實(shí)現(xiàn)的方法。

實(shí)現(xiàn)

迭代器模式基于兩個(gè)抽象類或接口,可以通過(guò)成對(duì)的具體類來(lái)實(shí)現(xiàn)。


image.png
  • Aggregate(抽象容器):應(yīng)該由所有類實(shí)現(xiàn)的抽象類,并且可以由迭代器遍歷。這對(duì)應(yīng)于java.util.Collection接口。
  • Iterator(抽象迭代器):抽象迭代器是迭代器抽象類,它定義遍歷容器對(duì)象的操作以及返回對(duì)象的操作。
  • ConcreteAggregate(具體容器):具體容器可以實(shí)現(xiàn)內(nèi)部不同的結(jié)構(gòu),但會(huì)暴露處理遍歷容器的具體迭代器。
  • ConcreteIterator(具體迭代器):這是處理特定具體容器類的具體迭代器。實(shí)際上,對(duì)于每個(gè)具體容器,必須實(shí)現(xiàn)一個(gè)具體迭代器。

實(shí)例

將書(shū)(Book)放到書(shū)架(BookShelf)中,并將書(shū)名按順序顯示。

Aggregate 接口

所要遍歷的集合的接口。實(shí)現(xiàn)了該接口的類將成為一個(gè)可以保存多個(gè)元素的集合,類似數(shù)組。
Aggregate接口中聲明的方法為iterator,作用為生成一個(gè)用于遍歷的迭代器。

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:54
 * @description: 表示集合的接口
 */
public interface Aggregate<E> {

    /**
     * 返回迭代器
     * @return iterator
     */
    Iterator<E> iterator();
}

Iterator 接口

作用為遍歷集合中元素,相當(dāng)于循環(huán)語(yǔ)句中的循環(huán)變量(for(int i =0;i<arr.lenth;i++),具體實(shí)現(xiàn)一個(gè)順序遍歷的迭代器。
hasNext()方法判斷是否存在下一個(gè);
next()方法獲取下一個(gè)元素。特殊說(shuō)明下,next()方法在獲取元素的同時(shí),要將計(jì)數(shù)器向下一個(gè)元素的計(jì)數(shù)加一。獲取的是當(dāng)前元素,并指向下一個(gè)元素。

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:54
 * @description: 遍歷集合的接口
 */
public interface Iterator<E> {

    /**
     * 是否有下一個(gè)元素
     * @return true false
     */
    boolean hasNext();

    /**
     * 獲取的是當(dāng)前元素,并將計(jì)數(shù)器向下一個(gè)元素的計(jì)數(shù)加一,指向下一個(gè)元素
     * @return E
     */
    E next();
}

BookShelf 類

書(shū)架類,作為存放書(shū)的集合類,實(shí)現(xiàn)Aggregate接口。實(shí)現(xiàn)了Aggregate接口的iterator方法。
主要點(diǎn)在iterator()方法,方法返回了遍歷書(shū)架時(shí)要用的BookShelfIterator類作為書(shū)架的迭代器。當(dāng)外部要遍歷書(shū)架時(shí)會(huì)調(diào)用該方法。

/**
 * @author: Jay Mitter
 * @date: 2020-08-25 22:27
 * @description: 表示書(shū)架的類
 */
public class BookShelf implements Aggregate<Book> {

    private List<Book> bookList;

    public BookShelf() {
        this.bookList = new ArrayList<>();
    }

    @Override
    public Iterator<Book> iterator() {
        return new BookShelfIterator(this);
    }

    public Book getBookAt(int index) {
        return this.bookList.get(index);
    }

    public void appendBook(Book book) {
        this.bookList.add(book);
    }

    public int getLength() {
        return bookList.size();
    }

}

BookShelfIterator 類

作為一個(gè)迭代器,要實(shí)現(xiàn)Iterator接口。index為迭代器當(dāng)前所指向的下標(biāo)。hasNext判斷還有沒(méi)有下一本。通過(guò)下標(biāo)和總數(shù)比較判斷。next獲取當(dāng)前書(shū),并指向下一個(gè)。

/**
 * @author: Jay Mitter
 * @date: 2020-08-25 22:30
 * @description: 遍歷書(shū)架的類
 */
public class BookShelfIterator implements Iterator<Book> {

    private BookShelf bookShelf;
    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        if (index < bookShelf.getLength()) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Book next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

測(cè)試:

    /**
     * 行為型模式——迭代器模式
     */
    @Test
    public void testBehaviorIterator() {
        BookShelf bookShelf = new BookShelf();
        bookShelf.appendBook(new Book("Around the World in 80 Days"));
        bookShelf.appendBook(new Book("Bible"));
        bookShelf.appendBook(new Book("Cinderella"));
        bookShelf.appendBook(new Book("Daddy-Long-Legs"));
        Iterator<Book> it = bookShelf.iterator();
        while (it.hasNext()) {
            Book book = it.next();
            System.out.println(book.getName());
        }
    }

為什么使用迭代器模式

如果是數(shù)組,直接使用for玄幻語(yǔ)句進(jìn)行遍歷處理不就可以了嗎?
為什么要在集合之外引入Iterator角色?
一個(gè)重要的理由:引入Iterator后可以將遍歷與實(shí)現(xiàn)分離開(kāi)來(lái)。

while (it.hasNext()) {
            Book book = it.next();
            System.out.println(book.getName());
        }

這里使用了Iterator的hasNext方法和next方法,并沒(méi)有調(diào)用BookShelf的方法。也就是說(shuō),這里的while循環(huán)并不依賴于BookShelf的實(shí)現(xiàn)。
例如在BookShelf的開(kāi)發(fā)人員決定放棄用數(shù)組來(lái)管理書(shū)本,而是java.util.Vector取而代之,會(huì)怎么樣呢。不管BookShelf如何變化,只要BookShelf的iterator方法能正確的返回Iterator的實(shí)例,即使不對(duì)上面的while循環(huán)做任何修改,代碼都可以正常工作。
對(duì)于BookShelf的調(diào)用者來(lái)說(shuō)真的太方便了,設(shè)計(jì)模式的作用就是幫助我們編寫(xiě)可復(fù)用的類。
所謂可復(fù)用,就是指將類實(shí)現(xiàn)為組件,當(dāng)一個(gè)組件發(fā)生改變時(shí),不需要對(duì)其他組件進(jìn)行修改或是只需要很小的修改即可應(yīng)對(duì)。這也就能理解為什么在示例程序中iterator方法返回值不是BookShelf類而是iterator類型了。這表明,程序就是要使用iterator的方法進(jìn)行編程而不是bookshelfiterator的方法。

在Java現(xiàn)有版本中的java.util.Iterator<E>類和java.util.Collection<E>類,是實(shí)現(xiàn)新容器和迭代器很好的例子。當(dāng)需要具有特定行為的容器時(shí),我們應(yīng)該考慮擴(kuò)展java.collection包中實(shí)現(xiàn)的一個(gè)類,而不是創(chuàng)建一個(gè)新類。

參考:http://www.itdecent.cn/p/3dd7b4e73561

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容