Java設計模式學習記錄-叠代器模式
前言
這次要介紹的是叠代器模式,也是一種行為模式。我現在覺得寫博客有點應付了,前陣子一天一篇,感覺這樣其實有點沒理解透徹就寫下來了,而且寫完後自己也沒有多看幾遍,上次在面試的時候被問到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設計模式學習記錄-叠代器模式