此次要介紹的是迭代器模式,也是一種行爲模式。我如今以爲寫博客有點應付了,前陣子一天一篇,感受這樣其實有點沒理解透徹就寫下來了,並且寫完後本身也沒有多看幾遍,上次在面試的時候被問到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設計模式概述。