設計模式之迭代器模式

迭代器模式(Iterator)用於在數據集合中按照順序遍歷集合,在遍歷的同時不須要暴露對象的內部表示,根據不一樣的需求咱們能夠採用不一樣的方式遍歷集合,它主要解決三個問題 一、可以遍歷一個集合對象。二、咱們不須要了解集合對象的內部結構。三、可以提供多種不一樣的遍歷方式。javascript

迭代器模式的適用場景

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

接下來就經過示例程序進行迭代器的學習。git

UML類圖

這裏寫圖片描述

這段程序的目的就是將書(Book)放到書架(BookShelf)中,並將書的名字按順序顯示出來。若是你對類圖不熟悉可移步 Java利器之UML類圖詳解程序員

接口

Aggregate 接口是所須要遍歷集合的接口,有一個iterator方法,該方法返回一個用於遍歷集合的迭代器,即建立出按順序訪問保存在我內部元素的對象。github

public interface Aggregate {
    public abstract Iterator iterator();
}複製代碼

當想要遍歷集合中元素時,能夠調用iterator方法來生成一個實現了Iterator接口的類的實例。對於Iterator接口就是遍歷集合元素的,相似於for循環,在此該接口簡單實現爲設計模式

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}複製代碼

對於這兩個方法應該很常見,hasNext()返回布爾類型表示是否有下一個元素,存在下一個元素就返回true,不然返回false,返回false時也就表示該集合元素已所有被遍歷,也是終止條件。next方法返回的就是集合中的當前指向元素,而且將迭代器指向下一個元素,而這些操做,都是Iterator的實現類中處理的。數組

Book類

public class Book {

    private String name;

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}複製代碼

BookShelf

該類就是表示書架的類,該類有一個數組books用於存放書籍,並提供了獲取數據,添加書籍及書籍數量的方法,因爲實現了Aggregate接口,則需重寫iterator方法,該方法返回BookShelfIterator類的實例做爲該類的iterator。當外部想要遍歷書架時就調用這個方法。性能優化

public class BookShelf implements Aggregate {
    private Book[] books;
    private int last;
    public BookShelf(int maxsize) {
        this.books = new Book[maxsize];
    }
    public Book getBookAt(int index) {
        return books[index];
    }
    public void appendBook(Book book) {
        this.books[last] = book;
        last++;
    }
    public int getLength() {
        return books.length;
    }
    @Override
    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}複製代碼

BookShelfIterator

該類是具體的迭代器,實現了Iterator 接口,是迭代器的具體實現,它包含了遍歷集合所必要的信息,bookShelf表示要遍歷的書架,index表示當前迭代器所指向書籍的下標,構造方法接收要遍歷的書架,並將index初始化爲0,hasNext方法是實現接口Iterator的方法,當index小於書架書的長度時表示有下一個數據,不然沒有返回false.next方法就是返回當前所指向的書籍,並將index加一指向下一本書,在這裏至關於for循環中i++.讓循環變量指向下一個元素。app

public class BookShelfIterator implements Iterator {
    private int index;
    private BookShelf bookShelf;

    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 Object next() {
        Book book=bookShelf.getBookAt(index);
        index++;
        return book;
    }

}複製代碼

至此迭代器以及實現完畢了,接下來寫測試類進行書架裝書和遍歷。ide

public class Main {

    public static void main(String[] args) {
        BookShelf bookShelf=new BookShelf(4);
        bookShelf.appendBook(new Book("圖解設計模式"));
        bookShelf.appendBook(new Book("將來簡史"));
        bookShelf.appendBook(new Book("Android性能優化"));
        bookShelf.appendBook(new Book("程序員修煉之道"));
        Iterator iterator=bookShelf.iterator();
        while (iterator.hasNext()) {
            Book book = (Book) iterator.next();
            System.out.println(book.getName());
        }
    }

}複製代碼

輸出信息

圖解設計模式
將來簡史
Android性能優化
程序員修煉之道複製代碼

優勢

說了這麼多,也許你會疑問爲何引入Iterator這種複雜的設計模式呢?若是是數組,直接for循環遍歷就能夠了。
固然引入迭代器模式最重要的理由是它能夠將遍歷和實現分離開來,在示例程序中

while (iterator.hasNext()) {
            Book book = (Book) iterator.next();
            System.out.println(book.getName());
        }複製代碼

它只使用了Iterator的hasNext和next方法,並無調用BookShelf的方法,也就是說這裏的循環並不依賴於BookShelf的實現。若是BookShelf開發者想放棄數組,用Vector取而代之,會如何?無論如何變化只要它能生成Iterator實例,即便不對while循環作修改,依然能保證程序正常運行。

在示例程序中,只是簡單的實現從前到後遍歷,固然也能夠是其餘方式,如從後向前,以及跳躍式遍歷。

好了,關於迭代器模式到這裏已經介紹完畢了。有問題歡迎留言指出,Have a wonderful day .

如需文章中所寫代碼,請移步GitHub查看

相關文章
相關標籤/搜索