Java設計模式學習記錄-迭代器模式 Java設計模式學習記錄-GoF設計模式概述

前言

此次要介紹的是迭代器模式,也是一種行爲模式。我如今以爲寫博客有點應付了,前陣子一天一篇,感受這樣其實有點沒理解透徹就寫下來了,並且寫完後本身也沒有多看幾遍,上次在面試的時候被問到java中的I/O的各類實現用到了什麼設計模式,我愣是想半天沒想出來了,人家還給提示了我也沒想出來,最後仍是面試官給出的答案,是裝飾模式,聽到答案後就恍然大悟了,前兩天剛看了裝飾模式,還寫下了I/O操做中的各類類都是用到了裝飾模式,後來想一想兩方面緣由形成的當時沒回答出來,一是面試時緊張就容易想不起來,二是對設計模式理解的仍是不夠透徹。因此之後寧肯寫博客慢一些也要將本身寫的東西理解透徹了。html

迭代器模式

概念介紹

迭代器模式,又稱遊標模式。這種模式提供一種方法訪問一個容器對象中各個元素,而又不須要暴露該對象的內部細節。這種模式其實咱們平常開發中也很常見,例以下面的場景:java

        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;
    }
}

書架類app

/**
 * 書架類
 */
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);
    }
}

書架迭代器ide

/**
 * 書架迭代器
 */
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;
    }
}

測試類post

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等集合均可以直接使用。

優勢

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

二、迭代器簡化了聚合類。聚合對象能夠不用本身再提供遍歷方法。

三、在迭代器模式中因爲引入了抽象層,增長新的聚合類和迭代器類都很方便,無須修改原有代碼,知足「開閉原則」的要求。

缺點

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

二、抽象迭代器設計難度相對較大,須要充分考慮到系統未來的擴展,,例如JDK內置迭代器Iterator就沒法實現逆向遍歷,若是須要實現逆向遍歷,只能經過其子類ListIterator等來實現,而ListIterator迭代器沒法用於操做Set類型的聚合對象。

適用場景

在如下狀況能夠考慮使用迭代器模式

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

二、須要爲一個聚合對象提供多種遍歷方式。

三、爲遍歷不一樣聚合結構提供統一的接口,該接口的實現類中爲不一樣的聚合結構提供不一樣的遍歷方式,而客戶端能夠一致性的操做該接口。

 

 

 

 

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

相關文章
相關標籤/搜索