Google Prettify

2015-03-31

Design Patter 103:輪流取得每個物件─Iterator簡介

上一篇介紹了Simple factor pattern, 今天來介紹一下Iterator。

Iterator,中譯迭代。簡單來說,Iterator 就是對集合裡的每個原素進行處理。

如果你在演算法裡有看到「對XX裡的每個YY…」,那你通常都會用到這個pattern。

for each y in x
    do blablabla
end for;

Iterator pattern 是對集合裡的每個原素(element)進行處理,因此他的構成的成份,第一個就是「集合」這個元件。(好像是廢話呢…) 第二個元件,是通常會有個指標,來記錄目前處理到那一個原素;第三個元件是需要處理一些事。程式在處理完那些事後,就將指標移往下一個原素。 第四個,就是這一段程式碼裡,通常會需要有個判斷式,來判斷是不是所有有東西都已經處理過。

接下來看一下實際例子。

假設我一個書櫃(BookShelf),有書櫃就有書(BookVo)…這次書是我們要講的重點了。

於是程式碼Iterator interface會是像這個樣子:

public interface Iterator<E> {
    boolean hasNext();
    E next();
}

由於我們要依次處理的是書(BookVo);所以實作這個interface的程式碼會是這個樣子。

private class BookVoIterator implements Iterator<BookVo> {

        private int index = -1;

        @Override
        public boolean hasNext() {
            return index < size - 1;
        }

        @Override
        public BookVo next() {
            index++;
            return bookVos[index];
        }
    }

next()是裡含了二個元件:第一個是指標(這不是C語言中的指標)的移動。第二個是「處理」;它除了在每次iterate時會將指標移到下一個原素之外,還做了一個動作:生出BookVo,並加以回傳。

hasNext()是第四個元件,它負責判斷是否還有下一個需要處理的原素,少了這元件,就會淪落成無窮迴圈(雖然有時需要這麼做…)。

那第一個元件呢? 再下面。

public class BookShelf implements Iterable<BookVo> {

    private BookVo[] bookVos;

    public BookVo findBook(String bookName) {
        for (Iterator<BookVo> it = iterator(); it.hasNext();) {
            BookVo bookVo = it.next();
            if (bookVo.getName().equals(bookName)) {
                return bookVo;
            }
        }
        return null;
    }
}

我們之前提到第一個元件,就是集合。 在這個例子裡,書的集合就是書櫃(BookShelf)。 先暫時別管Iteratorable這個interface; 這個interface現在還不是重點。 重要的是iterator的使用方式; 主要client端method(就是使用端、呼叫的程式)是findBook。顧名思義,就是從書名找書;怎麼找?一本一本找。 對書櫃裡的每一本書進行比對,直找到書名相同的書為止。 有注意到嗎? 「對XX裡的每個YY…」,我又用到這樣的描述了…。

總而言之Iterator的class diagram。

要怎麼用?

Java 1.5 有提供了enhance for loop的語法。 我還蠻常用這個。 主要是因為我認為電腦就是該執行重覆的工作;反正就是有一堆工作叫電腦去做,讓電腦針對所有工作任務裡的每一個工作(對XX裡的每個YY…),一項一項執行…。 在for each裡的集合,必需要實作Iterable interface。 因此,上面的findBook可改寫borrowBook

public BookVo borrowBook(String bookName) {
    ShelfFactory boFactory = context.getBean(ShelfFactory.class);
    BookShelf bookShelf = boFactory.getBookShelf("POMO");
    for (BookVo book : bookShelf) {
        if(book.getName().equals(bookName)){
            return book;
        }
    }
    return null;
}

可以看到for (BookVo book : bookShelf)的寫法要比單純的for迴圈的方式,要更簡單了一些。

題外話,Java是自1.5後才提供enhance foreach。 不過還記得我們之前有提過,Design pattern是無關乎程式語言的。 即始Java 1.5才提供foreach這種語法,早在更早之前,就有其他的Iteratgr介面可供使用。

結論

這一篇是使用與Simple factory相同的例子做示範,簡單介紹一下iterator pattern。 Iterator不只是可以next,也有可以previous、也可以直接firstlast。 沒錯,就是我們一般在網頁上最常看到的paging。

大家是否有注意到,我們常用的jdbc ResultSet也有相同的味道喔!

沒有留言 :

您或許對這些有興趣

Related Posts with Thumbnails

最後

謝謝您的閱讀,希望您可以有豐富的收獲。