前些時(shí)工作忙,中間停頓一段時(shí)間,今天繼續(xù)。向關(guān)注這里的文章的博友們表示抱歉。
今天說說一個(gè)簡(jiǎn)單的模式,迭代器模式(Iterator),他屬于行為模式中的一種。
[形成]
在Java程序中,在輸出List類型的對(duì)象時(shí)候,出現(xiàn)最多的程式塊就是:
1 for (int i = 0 ;i<list.size; i++){
2 XXX x = (XXX)list.get(i);
3 }
其中l(wèi)ist 是List 類型,里邊放著若干個(gè)XXX類型的對(duì)象。
這種 方式是采用i++遞增的方式來遍歷list中的所有對(duì)象來進(jìn)行相關(guān)操作。對(duì)于設(shè)計(jì)模式,把i的功能抽象劃的結(jié)果就是:Iterator Pattern
Iterate 中文的意思是“迭代,反復(fù)”,Iterator 的意思可以理解為“迭代器”。
[代碼示例]
示例程式是把書(Book)放到書架上(BookShelf)上,并依次輸出書名。
程式列表
名稱 |
說明 |
Aggregate |
表示已聚合的接口 |
Iterator |
執(zhí)行遞增,遍歷的接口 |
Book |
表示書籍的類 |
BookShelf |
表示書架的類 |
BookShelfIterator |
掃描書架的類 |
Main |
測(cè)試用的類 |
[UML圖]

[示例代碼和類的詮釋]
1 package Iterator;
2
3 import java.util.Iterator;
4
5 public interface Aggregate {
6 public abstract Iterator iterator();
7 }
8
Aggregate 接口:
該接口只聲明了一個(gè)方法,建立一個(gè)可以對(duì)應(yīng)聚合的Iterator.,當(dāng)需要遍歷某個(gè)聚合對(duì)象時(shí),調(diào)用Iterator方法可以建立一個(gè)實(shí)現(xiàn)Iterator接口的類的對(duì)象實(shí)例。
1 package Iterator;
2
3 public interface Iterator {
4 public abstract boolean hasNext();
5 public abstract Object next();
6 }
7
Iterator 接口:
這是該模式的核心接口,Iterator接口執(zhí)行元素的遞增,具有循環(huán)遍歷的功能。Iterator的接口的方法因需要而定,我們可以初步確定接口方法:
hasNext() :是檢查有沒有“下一個(gè)元素”,返回boolean.(有,返回true,,無,返回false)
next();取得“下一個(gè)元素”,同時(shí)把取對(duì)象的指針指向下一個(gè)元素,以便下次調(diào)用next方法的時(shí)候確實(shí)能取到下一個(gè)元素。這些具體實(shí)現(xiàn)還得看具體的實(shí)現(xiàn)Iterator接口的類的實(shí)現(xiàn)才知道
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 類:
表示書籍的類,比較簡(jiǎn)單,通過getName方法得到書的名字,書名是以構(gòu)造函數(shù)初始化對(duì)象的時(shí)候用參數(shù)來字號(hào)定。
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類:
該類是表現(xiàn)書架作用的類,保證實(shí)現(xiàn)Aggregate接口所聲明的Iterator方法里返回實(shí)現(xiàn)Iterator接口的實(shí)例。如果需要遍歷書架上的書,調(diào)用iterator方法。books數(shù)組存放的對(duì)象就是book,書架大小可以在一開始建立時(shí)設(shè)置大小,當(dāng)然我們可以不用數(shù)組而采用java.util.Vector,就可以往書架上放超過指定數(shù)量的書籍。
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字段則是指向目前該書的下標(biāo)。
構(gòu)造函數(shù)把傳過來的BookShelf對(duì)象實(shí)例儲(chǔ)存在bookShelf字段,將index設(shè)置為0.
實(shí)現(xiàn)的hasNext方法判斷是否有下一本書的標(biāo)準(zhǔn)是根據(jù)index是否小于書架上書籍的數(shù)量(表達(dá)式bookShelf.getLength()的值)來判斷。
next方法返回目前該書,并進(jìn)入到“下一個(gè)”。兩步:第一步先把取得當(dāng)面的書籍保留在book變量,然后把循環(huán)變量推到“下一個(gè)”。
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.通過調(diào)用書架的iterator方法得到
迭代器,來進(jìn)行循環(huán)遍歷
3.循環(huán)遍歷書籍,取出書,打印出書的名字。
回顧一下,在迭代器模式中幾個(gè)重要“角色”:
迭代器: 定義了訪問和遍歷元素的接口 ,它定義了能否取得下一個(gè)元素信息的的hasNext方法和取得下一個(gè)元素的next方法
具體的迭代器:實(shí)現(xiàn)了迭代器的接口,如本例的BookShelfIterator,掌握遍歷時(shí)的重要信息。
聚合:定義了建立了Iterator的接口。如本例的:Aggregate接口,定義了Iterator方法
具體聚合:實(shí)現(xiàn)了聚合的所定義的接口,如本例的BookShelf,它實(shí)現(xiàn)了Iterator方法。
[拓展思考]
有人回想,干嘛搞這么麻煩,用一個(gè)for不就是可以遍歷數(shù)組或List碼?思考一下迭代器的結(jié)構(gòu)。Iterator是把定義和實(shí)現(xiàn)分開
while(it.
hasNext()){
Book book = (Book)it.
next();
System.out.println(" "+book.getName());
}
這里我只調(diào)用了Iterator接口的hasNext和next方法,并沒有調(diào)用BookShelf實(shí)現(xiàn)遍歷是需要的方法,如:getBookAt()。這里的while不會(huì)收到BookShelf的實(shí)現(xiàn)影響。
假設(shè)這里我們不采用數(shù)組來管理BookShelf,而采取與Java.util.Vector來管理。無論BookShelf的如何修改,都Main測(cè)試程序里無需修改任何程序就可以運(yùn)行,這就是設(shè)計(jì)模式的優(yōu)勢(shì)。設(shè)計(jì)模式是為了提高類的服用率,如果把一個(gè)零件修改了,就不想要修改其他使用了改零件的部分。