<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
    主站蜘蛛池模板: 一级**爱片免费视频| 国产亚洲av片在线观看16女人 | 亚洲国产一二三精品无码| 亚洲乱码国产一区三区| 亚洲日本va在线视频观看| 国产亚洲精品国产| 亚洲精品福利在线观看| 亚洲成aⅴ人片久青草影院按摩| 激情婷婷成人亚洲综合| 伊人免费在线观看| 亚洲黄色免费电影| 免费va在线观看| 亚洲av无码潮喷在线观看| 国产精品亚洲片在线va| 国产亚洲女在线线精品| 日本在线免费播放| 成人免费午夜视频| 亚洲精品午夜国产VA久久成人| 亚洲蜜芽在线精品一区| 美女尿口扒开图片免费| 最近高清中文字幕免费| 亚洲高清视频一视频二视频三| 亚洲综合激情六月婷婷在线观看| 亚洲爆乳成av人在线视菜奈实| 免费在线中文日本| 国产免费观看a大片的网站| 伊人久久大香线蕉亚洲| 亚洲最大天堂无码精品区| 青柠影视在线观看免费高清| 好爽好紧好大的免费视频国产| 亚洲AV人无码激艳猛片| 美女裸免费观看网站| 免免费国产AAAAA片| 国产亚洲精品一品区99热| 日本系列1页亚洲系列| 一区二区三区在线免费看| 国产91精品一区二区麻豆亚洲| 亚洲国产成人AV在线播放 | 无码专区—VA亚洲V天堂| 污污视频免费观看网站| 午夜成年女人毛片免费观看|