1. 程式人生 > >Java設計模式學習記錄-叠代器模式

Java設計模式學習記錄-叠代器模式

reg 情況 java .get 職責 結構 ride 測試 寧可

前言

這次要介紹的是叠代器模式,也是一種行為模式。我現在覺得寫博客有點應付了,前陣子一天一篇,感覺這樣其實有點沒理解透徹就寫下來了,而且寫完後自己也沒有多看幾遍,上次在面試的時候被問到java中的I/O的各種實現用到了什麽設計模式,我楞是想半天沒想出來了,人家還給提示了我也沒想出來,最後還是面試官給出的答案,是裝飾模式,聽到答案後就恍然大悟了,前兩天剛看了裝飾模式,還寫下了I/O操作中的各種類都是用到了裝飾模式,後來想想兩方面原因造成的當時沒回答出來,一是面試時緊張就容易想不起來,二是對設計模式理解的還是不夠透徹。所以以後寧可寫博客慢一些也要將自己寫的東西理解透徹了。

叠代器模式

概念介紹

叠代器模式,又稱遊標模式。這種模式提供一種方法訪問一個容器對象中各個元素,而又不需要暴露該對象的內部細節

。這種模式其實我們日常開發中也很常見,例如下面的場景:

        java.util.Iterator<String> it = list.iterator();
        
        while (it.hasNext()){
            //using "it.next();" do some business logic
        }

這樣來理解簡單一些,下面還是通過具體的場景例子來實現叠代器模式。

舉例

一個書架上放著好幾本書,現在我想知道書架上都有哪些書,並且都把書名打印出來。那麽書架就可以具有叠代的功能,能把它存放的所有書籍都叠代出來。用代碼實現如下:

定義一個叠代器接口,包含檢測是否還有下一個元素的方法和獲得下一個元素的方法

/**
 * 叠代器接口
 */
public interface Iterator {

    /**
     * 檢測是否還有下一個元素
     * @return
     */
    public abstract boolean hasNext();

    /**
     * 獲得下一個元素
     * @return
     */
    public abstract Object next();

}

定義含有叠代器對象的接口

/**
 * 只有實現此接口的才可以獲得叠代器對象
 
*/ public interface Aggregate { /** * 獲得叠代器對象 * @return */ public abstract Iterator iterator(); }

書籍類

/**
 * 書籍類
 */
public class Book {
    
    //書籍名稱
    private String name = "";

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

    /**
     * 獲得書籍名稱
     * @return
     */
    public String getName(){
        return name;
    }
}

書架類

/**
 * 書架類
 */
public class BookShelf implements Aggregate{

    private Book[] books;

    private int last = 0;

    public BookShelf(int maxSize){
        this.books = new Book[maxSize];
    }

    /**
     * 獲得書籍
     * @param index
     * @return
     */
    public Book getBookAt(int index){

        return books[index];

    }

    /**
     * 添加書籍
     * @param book
     */
    public void appendBook(Book book){
        this.books[last] = book;
        last++;
    }

    /**
     * 獲得書架上的書籍數量
     * @return
     */
    public int getLength(){
        return books.length;
    }

    /**
     * 獲得書架叠代器對象
     * @return
     */
    @Override
    public Iterator iterator(){
        return new BookShelfIterator(this);
    }
}

書架叠代器

/**
 * 書架叠代器
 */
public class BookShelfIterator implements Iterator {

    private BookShelf bookShelf;
    private int index;

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

    /**
     * 檢測是否還有下一本書
     * @return
     */
    @Override
    public boolean hasNext() {
        if(index<bookShelf.getLength()){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 返回下一本書
     * @return
     */
    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

測試類

public class Client {


    public static void main(String[] args) {
        //創建一個書架
        BookShelf bookShelf = new BookShelf(5);
        //向書架中添加書籍
        bookShelf.appendBook(new Book("深入理解Java虛擬機"));
        bookShelf.appendBook(new Book("Java編程思想"));
        bookShelf.appendBook(new Book("高性能MySQL"));
        bookShelf.appendBook(new Book("Effective Java 中文版"));
        bookShelf.appendBook(new Book("數據結構與算法分析Java語言描述"));
        //獲得書架叠代器
        Iterator iterator = bookShelf.iterator();
        //叠代
        while (iterator.hasNext()){
            Book book = (Book) iterator.next();
            System.out.println(book.getName());
        }

    }

}

運行結果

深入理解Java虛擬機
Java編程思想
高性能MySQL
Effective Java 中文版
數據結構與算法分析Java語言描述

上面的這個例子就是實現了叠代器模式,可以看出來是在客戶端和容器間加入了叠代器,這樣就很好的避免容器內部細節的暴露,而且也使得設計符合“單一職責原則”。

叠代器模式的結構

技術分享圖片

叠代器模式主要由以下角色組成

抽象叠代器角色(Iterator):抽象叠代器角色定義訪問和遍歷元素的接口。上面例子中的Iterator接口就是代表的這個角色。

具體叠代器角色(Concrete Iterator):具體叠代器角色要實現叠代器接口, 並要記錄遍歷中的當前位置。上面例子中BookShelfIterator類就是代表的這個角色。

容器角色(Aggregate):容器角色負責提供創建具體叠代器角色的接口。上面的例子中的Aggregate接口代表的就是這個角色。

具體容器角色(Concrete Aggregate):具體容器角色實現創建具體叠代器角色的接口,這個具體叠代器角色與該容器的結構相關。上面例子中書架類BookShelf

代表的就是這個角色。

總結

叠代器模式是一種使用頻率非常高的設計模式,通過引入叠代器可以將數據的遍歷功能從聚合對象中分離出來,聚合對象只負責存儲數據,而遍歷數據由叠代器實現完成。Java語言類庫中已經實現了叠代器模式,在實際開發中我們直接使用已經定義好的叠代器就可以了,像List、Set等集合都可以直接使用。

優點

1、它支持以不同的方式遍歷一個聚合對象,在同一個聚合對象上可以定義多種遍歷方式。替換叠代器就可以切換遍歷方法。

2、叠代器簡化了聚合類。聚合對象可以不用自己再提供遍歷方法。

3、在叠代器模式中由於引入了抽象層,增加新的聚合類和叠代器類都很方便,無須修改原有代碼,滿足“開閉原則”的要求。

缺點

1、由於叠代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的叠代器來,類的個數成對增加,這在一定程度上增加了系統的復雜性。

2、抽象叠代器設計難度相對較大,需要充分考慮到系統將來的擴展,,例如JDK內置叠代器Iterator就無法實現逆向遍歷,如果需要實現逆向遍歷,只能通過其子類ListIterator等來實現,而ListIterator叠代器無法用於操作Set類型的聚合對象。

適用場景

在以下情況可以考慮使用叠代器模式

1、訪問一個聚合對象的內容而無須暴露它的內部表示。將聚合對象的訪問與內部數據的存儲分離,使得訪問聚合對象時無須了解其內部實現細節。

2、需要為一個聚合對象提供多種遍歷方式。

3、為遍歷不同聚合結構提供統一的接口,該接口的實現類中為不同的聚合結構提供不同的遍歷方式,而客戶端可以一致性的操作該接口。

想了解更多的設計模式請查看Java設計模式學習記錄-GoF設計模式概述。

Java設計模式學習記錄-叠代器模式