前些時工作忙,中間停頓一段時間,今天繼續。向關注這里的文章的博友們表示抱歉。
今天說說一個簡單的模式,迭代器模式(Iterator),他屬于行為模式中的一種。
[形成]
在Java程序中,在輸出List類型的對象時候,出現最多的程式塊就是:
1 for (int i = 0 ;i<list.size; i++){
2 XXX x = (XXX)list.get(i);
3 }
其中list 是List 類型,里邊放著若干個XXX類型的對象。
這種 方式是采用i++遞增的方式來遍歷list中的所有對象來進行相關操作。對于設計模式,把i的功能抽象劃的結果就是:Iterator Pattern
Iterate 中文的意思是“迭代,反復”,Iterator 的意思可以理解為“迭代器”。
[代码示例]
示例程式是把書(Book)放到書架上(BookShelf)上,并依次輸出書名。
程式列表
名稱 |
說明 |
Aggregate |
表示已聚合的接口 |
Iterator |
執行遞增,遍歷的接口 |
Book |
表示書籍的類 |
BookShelf |
表示書架的類 |
BookShelfIterator |
掃描書架的類 |
Main |
測試用的類 |
[UML图]
[示例代码和类的诠释]
1 package Iterator;
2
3 import java.util.Iterator;
4
5 public interface Aggregate {
6 public abstract Iterator iterator();
7 }
8
Aggregate 接口:
該接口只聲明了一個方法,建立一個可以對應聚合的Iterator.,當需要遍歷某個聚合對象時,調用Iterator方法可以建立一個實現Iterator接口的類的對象實例。
1 package Iterator;
2
3 public interface Iterator {
4 public abstract boolean hasNext();
5 public abstract Object next();
6 }
7
Iterator 接口:
這是該模式的核心接口,Iterator接口執行元素的遞增,具有循環遍歷的功能。Iterator的接口的方法因需要而定,我們可以初步確定接口方法:
hasNext() :是檢查有沒有“下一個元素”,返回boolean.(有,返回true,,無,返回false)
next();取得“下一個元素”,同時把取對象的指針指向下一個元素,以便下次調用next方法的時候確實能取到下一個元素。這些具體實現還得看具體的實現Iterator接口的類的實現才知道
1 package Iterator;
2
3 public class Book {
4 private String name = "";
5
6 public Book(String name) {
7 this.name = name;
8 }
9
10 public String getName() {
11 return name;
12 }
13 }
14
Book 類:
表示書籍的類,比較簡單,通過getName方法得到書的名字,書名是以構造函數初始化對象的時候用參數來字號定。
1 package Iterator;
2
3 public class BookShelf implements Aggregate{
4 private Book[] books;
5 private int last = 0;
6
7 public BookShelf(int maxsize){
8 this.books = new Book[maxsize];
9 }
10
11 public Book getBookAt(int index){
12 return books[index];
13 }
14 public void appendBook(Book book){
15 this.books[last] = book;
16 last++;
17 }
18
19 public int getLength(){
20 return last;
21 }
22 public Iterator iterator(){
23 return new BookShelfIterator(this);
24 }
25 }
26
BookShelfl類:
該類是表現書架作用的類,保證實現Aggregate接口所聲明的Iterator方法里返回實現Iterator接口的實例。如果需要遍歷書架上的書,調用iterator方法。books數組存放的對象就是book,書架大小可以在一開始建立時設置大小,當然我們可以不用數組而采用java.util.Vector,就可以往書架上放超過指定數量的書籍。
1 package Iterator;
2
3 public class BookShelfIterator implements Iterator{
4 private BookShelf bookShelf;
5 private int index;
6 public BookShelfIterator(BookShelf bookShelf){
7 this.bookShelf = bookShelf;
8 this.index =0;
9 }
10
11 public boolean hasNext(){
12 if(index < bookShelf.getLength()){
13 return true;
14 }else{
15 return false;
16 }
17 }
18
19 public Object next(){
20 Book book = bookShelf.getBookAt(index);
21 index++;
22 return book;
23 }
24
25 }
26
BookShelfIterator類:
字段bookShelf指定BookShelfIterator所要掃描的書架,而index字段則是指向目前該書的下標。
構造函數把傳過來的BookShelf對象實例儲存在bookShelf字段,將index設置為0.
實現的hasNext方法判斷是否有下一本書的標準是根據index是否小于書架上書籍的數量(表達式bookShelf.getLength()的值)來判斷。
next方法返回目前該書,并進入到“下一個”。兩步:第一步先把取得當面的書籍保留在book變量,然后把循環變量推到“下一個”。
1 package Iterator;
2
3 public class Main {
4 /**
5 * @param args
6 */
7 public static void main(String[] args) {
8 BookShelf bookShelf = new BookShelf(3);
9 bookShelf.appendBook(new Book("book1"));
10 bookShelf.appendBook(new Book("book2"));
11 bookShelf.appendBook(new Book("book3"));
12 Iterator it = bookShelf.iterator();
13 while(it.hasNext()){
14 Book book = (Book)it.next();
15 System.out.println(" "+book.getName());
16 }
17 }
18
19 }
20
Main類:
1.先放三本書上架
2.通過調用書架的iterator方法得到
迭代器,來進行循環遍歷
3.循環遍歷書籍,取出書,打印出書的名字。
回顧一下,在迭代器模式中幾個重要“角色”:
迭代器: 定義了訪問和遍歷元素的接口 ,它定義了能否取得下一個元素信息的的hasNext方法和取得下一個元素的next方法
具體的迭代器:實現了迭代器的接口,如本例的BookShelfIterator,掌握遍歷時的重要信息。
聚合:定義了建立了Iterator的接口。如本例的:Aggregate接口,定義了Iterator方法
具體聚合:實現了聚合的所定義的接口,如本例的BookShelf,它實現了Iterator方法。
[拓展思考]
有人回想,干嘛搞這么麻煩,用一個for不就是可以遍歷數組或List碼?思考一下迭代器的結構。Iterator是把定義和實現分開
while(it.
hasNext()){
Book book = (Book)it.
next();
System.out.println(" "+book.getName());
}
這里我只調用了Iterator接口的hasNext和next方法,并沒有調用BookShelf實現遍歷是需要的方法,如:getBookAt()。這里的while不會收到BookShelf的實現影響。
假設這里我們不采用數組來管理BookShelf,而采取與Java.util.Vector來管理。無論BookShelf的如何修改,都Main測試程序里無需修改任何程序就可以運行,這就是設計模式的優勢。設計模式是為了提高類的服用率,如果把一個零件修改了,就不想要修改其他使用了改零件的部分。