<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    深入淺出Java設計模式之迭代器模式


    迭代這個名詞對于熟悉Java的人來說絕對不陌生。我們常常使用JDK提供的迭代接口進行java collection的遍歷:

    Iterator it = list.iterator();
    while(it.hasNext()){
    //using “it.next();”do some businesss logic
    }

    而這就是關于迭代器模式應用很好的例子。

    二、 定義與結構

    迭代器(Iterator)模式,又叫做游標(Cursor)模式。GOF給出的定義為:提供一種方法訪問一個容器(container)對象中各個元素,而又不需暴露該對象的內部細節。

    從定義可見,迭代器模式是為容器而生。很明顯,對容器對象的訪問必然涉及到遍歷算法。你可以一股腦的將遍歷方法塞到容器對象中去;或者根本不去提供什么遍歷算法,讓使用容器的人自己去實現去吧。這兩種情況好像都能夠解決問題。

    然而在前一種情況,容器承受了過多的功能,它不僅要負責自己“容器”內的元素維護(添加、刪除等等),而且還要提供遍歷自身的接口;而且由于遍歷狀態保存的問題,不能對同一個容器對象同時進行多個遍歷。第二種方式倒是省事,卻又將容器的內部細節暴露無遺。

    而迭代器模式的出現,很好的解決了上面兩種情況的弊端。先來看下迭代器模式的真面目吧。

    迭代器模式由以下角色組成:

    1) 迭代器角色(Iterator):迭代器角色負責定義訪問和遍歷元素的接口。

    2) 具體迭代器角色(Concrete Iterator):具體迭代器角色要實現迭代器接口,并要記錄遍歷中的當前位置。

    3) 容器角色(Container):容器角色負責提供創建具體迭代器角色的接口。

    4) 具體容器角色(Concrete Container):具體容器角色實現創建具體迭代器角色的接口——這個具體迭代器角色于該容器的結構相關。

    迭代器模式的類圖如下:


    從結構上可以看出,迭代器模式在客戶與容器之間加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器內部細節的暴露,而且也使得設計符號“單一職責原則”。

    注意,在迭代器模式中,具體迭代器角色和具體容器角色是耦合在一起的——遍歷算法是與容器的內部細節緊密相關的。為了使客戶程序從與具體迭代器角色耦合的困境中脫離出來,避免具體迭代器角色的更換給客戶程序帶來的修改,迭代器模式抽象了具體迭代器角色,使得客戶程序更具一般性和重用性。這被稱為多態迭代。

    三、 舉例

    由于迭代器模式本身的規定比較松散,所以具體實現也就五花八門。我們在此僅舉一例,根本不能將實現方式一一呈現。因此在舉例前,我們先來列舉下迭代器模式的實現方式。

    1.迭代器角色定義了遍歷的接口,但是沒有規定由誰來控制迭代。在Java collection的應用中,是由客戶程序來控制遍歷的進程,被稱為外部迭代器;還有一種實現方式便是由迭代器自身來控制迭代,被稱為內部迭代器。外部 迭代器要比內部迭代器靈活、強大,而且內部迭代器在java語言環境中,可用性很弱。

    2.在迭代器模式中沒有規定誰來實現遍歷算法。 好像理所當然的要在迭代器角色中實現。因為既便于一個容器上使用不同的遍歷算法,也便于將一種遍歷算法應用于不同的容器。但是這樣就破壞掉了容器的封裝 ——容器角色就要公開自己的私有屬性,在java中便意味著向其他類公開了自己的私有屬性。

    那我們把它放到容器角色里來實現好了。這樣迭代器角色就被架空為僅僅存放一個遍歷當前位置的功能。但是遍歷算法便和特定的容器緊緊綁在一起了。

    而在Java Collection的應用中,提供的具體迭代器角色是定義在容器角色中的內部類。這樣便保護了容器的封裝。但是同時容器也提供了遍歷算法接口,你可以擴展自己的迭代器。

    好了,我們來看下Java Collection中的迭代器是怎么實現的吧。

    //迭代器角色,僅僅定義了遍歷接口

    public interface Iterator {
    boolean hasNext();
    Object next();
    void remove();
    }

    //容器角色,這里以List為例。它也僅僅是一個接口,就不羅列出來了
    //具體容器角色,便是實現了List接口的ArrayList等類。為了突出重點這里指羅列和迭代器相關的內容
    //具體迭代器角色,它是以內部類的形式出來的。AbstractList是為了將各個具體容器角色的公共部分提取出來而存在的。

    public abstract class AbstractList extends AbstractCollection implements List {
    ……
    //這個便是負責創建具體迭代器角色的工廠方法
    public Iterator iterator() {
    return new Itr();
    }

    //作為內部類的具體迭代器角色

    private class Itr implements Iterator {
    int cursor = 0;
    int lastRet = -1;
    int expectedModCount = modCount;

    public boolean hasNext() {
    return cursor != size();
    }

    public Object next() {
    checkForComodification();
    try {
    Object next = get(cursor);
    lastRet = cursor++;
    return next;
    } catch(IndexOutOfBoundsException e) {
    checkForComodification();
    throw new NoSuchElementException();
    }
    }

    public void remove() {
    if (lastRet == -1)
    throw new IllegalStateException();
    checkForComodification();

    try {
    AbstractList.this.remove(lastRet);
    if (lastRet < cursor)
    cursor--;
    lastRet = -1;
    expectedModCount = modCount;
    } catch(IndexOutOfBoundsException e) {
    throw new ConcurrentModificationException();
    }
    }

    final void checkForComodification() {
    if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
    }
    }

    至于迭代器模式的使用。正如引言中所列那樣,客戶程序要先得到具體容器角色,然后再通過具體容器角色得到具體迭代器角色。這樣便可以使用具體迭代器角色來遍歷容器了……

    四、 實現自己的迭代器

    在實現自己的迭代器的時候,一般要操作的容器有支持的接口才可以。而且我們還要注意以下問題:

    在迭代器遍歷的過程中,通過該迭代器進行容器元素的增減操作是否安全呢?

    在容器中存在復合對象的情況,迭代器怎樣才能支持深層遍歷和多種遍歷呢?

    以上兩個問題對于不同結構的容器角色,各不相同,值得考慮。

    五、 適用情況

    由上面的講述,我們可以看出迭代器模式給容器的應用帶來以下好處:

    1) 支持以不同的方式遍歷一個容器角色。根據實現方式的不同,效果上會有差別。

    2) 簡化了容器的接口。但是在java Collection中為了提高可擴展性,容器還是提供了遍歷的接口。

    3) 對同一個容器對象,可以同時進行多個遍歷。因為遍歷狀態是保存在每一個迭代器對象中的。

    由此也能得出迭代器模式的適用范圍:

    1) 訪問一個容器對象的內容而無需暴露它的內部表示。

    2) 支持對容器對象的多種遍歷。

    3) 為遍歷不同的容器結構提供一個統一的接口(多態迭代)。

    六、 總結

    迭代器模式在我們的應用中很廣泛,希望本文能幫助你理解它。如有不對之處,還請不吝指正。

    posted on 2008-03-11 12:51 gembin 閱讀(517) 評論(0)  編輯  收藏 所屬分類: JavaSE

    導航

    統計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: www国产亚洲精品久久久日本| 最近新韩国日本免费观看| 成年性羞羞视频免费观看无限| 亚洲综合综合在线| 久久久久久毛片免费播放| 亚洲午夜在线电影| **aaaaa毛片免费| 亚洲小说图片视频| 免费无码A片一区二三区| 亚洲欧美中文日韩视频| 国产美女无遮挡免费网站| 杨幂最新免费特级毛片| 中文字幕亚洲综合久久菠萝蜜| 中文字幕在线观看免费| 亚洲爱情岛论坛永久| 91香蕉成人免费网站| 亚洲国产成人久久一区二区三区| 国产大片51精品免费观看| 国产精品极品美女自在线观看免费| 国产亚洲精品不卡在线| 无码人妻久久一区二区三区免费 | 成年女人看片免费视频播放器| 亚洲国产精品免费观看 | 国产精品国产免费无码专区不卡 | 亚洲一区二区三区高清视频| 午夜视频在线观看免费完整版| 欧美日韩亚洲精品| 亚洲中文字幕久久精品无码APP| 国产成人精品无码免费看| 亚洲一区二区三区国产精品无码| 国产做床爱无遮挡免费视频| 9久热这里只有精品免费| 亚洲蜜芽在线精品一区| 精品国产一区二区三区免费看| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 亚洲中文字幕在线第六区| 日本免费人成视频在线观看| 亚洲狠狠成人综合网| 红杏亚洲影院一区二区三区| 五月婷婷在线免费观看| 又硬又粗又长又爽免费看|