18.迭代器模式Iterator

1.初識迭代器模式

提供一種方法順序訪問一個聚合對象中各個元素椎扬,而又不需暴露該對象的內(nèi)部表示。

  • Iterator:迭代器接口。定義訪問和遍歷元素的接口掉弛。
    ConcreteIterator:具體的迭代器實現(xiàn)對象戒财。實現(xiàn)對聚合對象的遍歷热监,并跟蹤遍歷時的當(dāng)前位置。
    Aggregate:聚合對象饮寞。定義創(chuàng)建相應(yīng)迭代器對象的接口孝扛。
    ConcreteAggregate:具體聚合對象列吼。實現(xiàn)創(chuàng)建相應(yīng)的迭代器對象。

2.體會迭代器模式

2.1 場景問題——工資表數(shù)據(jù)的整合

這個項目的背景是這樣的苦始,項目的客戶方收購了一家小公司寞钥,這家小公司有自己的工資系統(tǒng),現(xiàn)在需要整合到客戶方已有的工資系統(tǒng)上陌选。

現(xiàn)在除了要把兩個工資系統(tǒng)整合起來外理郑,老板還希望能夠通過決策輔助系統(tǒng)來統(tǒng)一查看工資數(shù)據(jù),他不想看到兩份不同的工資表咨油。那么應(yīng)該如何實現(xiàn)呢您炉?

有何問題:
本來就算內(nèi)部描述形式不一樣,只要不需要整合在一起役电,兩個系統(tǒng)單獨輸
出自己的工資表赚爵,是沒有什么問題的。但是宴霸,老板還希望能夠以一個統(tǒng)一的方式來查看所有的工資數(shù)據(jù)囱晴,也就是說從外部看起來,兩個系統(tǒng)輸出的工資表應(yīng)該是一樣的瓢谢。

經(jīng)過分析畸写,要滿足老板的要求,而且要讓兩邊的系統(tǒng)改動都盡可能的小的
話氓扛,問題的核心就在于如何能夠以一種統(tǒng)一的方式來提供工資數(shù)據(jù)給決策輔助系統(tǒng)枯芬,換句說來說就是:如何能夠以一個統(tǒng)一的方式來訪問內(nèi)部實現(xiàn)不同的聚合對象。

2.2 使用模式的解決方案

3.理解迭代器模式

3.1 認識迭代器模式

3.1.1 迭代器模式的功能

迭代器模式的功能主要在于提供對聚合對象的迭代訪問采郎。迭代器就圍繞著
這個“訪問”做文章千所,延伸出很多的功能來。比如:

  • 1)以不同的方式遍歷聚合對象蒜埋,比如向前淫痰、向后等
  • 2)對同一個聚合同時進行多個遍歷
  • 3)以不同的遍歷策略來遍歷聚合,比如是否需要過濾等
  • 4)多態(tài)迭代整份,含義是:為不同的聚合結(jié)構(gòu)待错,提供統(tǒng)一的迭代接口,也就是說通過一個迭代接口可以訪問不同的聚合結(jié)構(gòu)烈评,這就叫做多態(tài)迭代火俄。上面的示例就已經(jīng)實現(xiàn)了多態(tài)迭代,事實上讲冠,標(biāo)準(zhǔn)的迭代模式實現(xiàn)基本上都是支持多態(tài)迭代的瓜客。

但是請注意:多態(tài)迭代可能會帶來類型安全的問題,可以考慮使用泛型

3.1.2 迭代器模式的關(guān)鍵思想

聚合對象的類型很多,如果對聚合對象的迭代訪問跟聚合對象本身融合在一起的話谱仪,會嚴重影響到聚合對象的可擴展性和可維護性玻熙。

因此迭代器模式的關(guān)鍵思想就是把對聚合對象的遍歷和訪問從聚合對象中分離出來,放入到單獨的迭代器中芽卿,這樣聚合對象會變得簡單一些揭芍;而且迭代器和聚合對象可以獨立的變化和發(fā)展,會大大加強系統(tǒng)的靈活性卸例。

3.1.3 內(nèi)部迭代器和外部迭代器

所謂內(nèi)部迭代器称杨,指的是由迭代器自己來控制迭代下一個元素的步驟,客戶端無法干預(yù)筷转,因此姑原,如果想要在迭代的過程中完成工作的話,客戶端就需要把操作傳給迭代器呜舒,迭代器在迭代的時候會在每個元素上執(zhí)行這個操作锭汛,類似于Java的回調(diào)機制。

所謂外部迭代器袭蝗,指的是由客戶端來控制迭代下一個元素的步驟唤殴,像前面的示例一樣,客戶端必須顯示的調(diào)用next來迭代下一個元素到腥。

總體來說外部迭代器比內(nèi)部迭代器要靈活一些朵逝,因此我們常見的實現(xiàn)多屬于外部迭代器,前面的例子也是實現(xiàn)的外部迭代器乡范。

3.1.4 Java中最簡單的統(tǒng)一訪問聚合的方式

如果只是想要使用一種統(tǒng)一的訪問方式來訪問聚合對象配名,在Java中有更簡單的方式,簡單到幾乎什么都不用做晋辆,利用Java 5以上版本本身的特性即可渠脉。

但是請注意,這只是從訪問形式上一致了瓶佳,但是也暴露了聚合的內(nèi)部實現(xiàn)芋膘,因此并不能算是標(biāo)準(zhǔn)迭代器模式的實現(xiàn),但是從某種意義上說霸饲,可以算是隱含的實現(xiàn)了部分迭代器模式的功能索赏。

3.2 使用Java的迭代器

大家都知道,在java.util包里面有一個Iterator的接口贴彼,在Java中實現(xiàn)迭
代器模式是非常簡單的,而且java的集合框架中的聚合對象埃儿,基本上都是提供了迭代器的器仗。

下面就來把前面的例子改成用Java中的迭代器實現(xiàn),一起來看看有些什么改變。

  • 1)不再需要自己實現(xiàn)的Iterator接口精钮,直接實現(xiàn)java.util.Iterator接口就可以了威鹿,所有使用自己實現(xiàn)的Iterator接口的地方都需要修改過來
  • 2)Java中Iterator接口跟前面自己定義的接口相比,需要實現(xiàn)的方法是不一樣的
  • 3)集合已經(jīng)提供了Iterator轨香,那么CollectionIteratorImpl類就不需要了忽你,直接去掉

3.3 帶迭代策略的迭代器

由于迭代器模式把聚合對象和訪問聚合的機制實現(xiàn)了分離,所以可以在迭代器上實現(xiàn)不同的迭代策略臂容,最為典型的就是實現(xiàn)過濾功能的迭代器。

在實際開發(fā)中,對于經(jīng)常被訪問的一些數(shù)據(jù)可以使用緩存姑裂,把這些數(shù)據(jù)存放在內(nèi)存中到旦。但是不同的業(yè)務(wù)功能需要訪問的數(shù)據(jù)是不同的,還有不同的業(yè)務(wù)訪問權(quán)限能訪問的數(shù)據(jù)也是不同的球散,對于這種情況尿赚,就可以使用實現(xiàn)過濾功能的迭代器,讓不同功能使用不同的迭代器來訪問蕉堰。當(dāng)然凌净,這種情況也可以結(jié)合策略模式來實現(xiàn)。

在實現(xiàn)過濾功能的迭代器中屋讶,又有兩種常見的需要過濾的情況冰寻,一種是對數(shù)據(jù)進行整條過濾,比如只能查看自己部門的數(shù)據(jù)丑婿;另外一種情況是對數(shù)據(jù)進行部分過濾性雄,比如某些人不能查看工資數(shù)據(jù)。

3.4 誰定義遍歷算法的問題

在迭代器模式的實現(xiàn)中羹奉,常見有兩個地方可以來定義遍歷算法秒旋,一個就是聚合對象本身,另外一個就是迭代器負責(zé)遍歷算法诀拭。

在聚合對象本身定義遍歷的算法這種情況下迁筛,通常會在遍歷過程中,用迭代器來存儲當(dāng)前迭代的狀態(tài)耕挨,這種迭代器被稱為游標(biāo)细卧,因為它僅用來指示當(dāng)前的位置。

在迭代器里面定義遍歷算法筒占,會易于在相同的聚合上使用不同的迭代算法贪庙,同時也易于在不同的聚合上重用相同的算法。比如上面帶策略的迭代器的示例翰苫,迭代器把需要迭代的數(shù)據(jù)從聚合對象中取出并存放到自己對象里面止邮,然后再迭代自己的數(shù)據(jù)这橙,這樣一來,除了剛開始創(chuàng)建迭代器的時候需要訪問聚合對象外导披,真正迭代過程已經(jīng)跟聚合對象無關(guān)了屈扎。

3.5 雙向迭代器

所謂雙向迭代器的意思就是:可以同時向前和向后遍歷數(shù)據(jù)的迭代器。

在Java util包中的ListIterator接口就是一個雙向迭代器的示例撩匕,當(dāng)然自己實現(xiàn)雙向迭代器也非常容易鹰晨,只要在自己的Iterator接口中添加向前的判斷和向前獲取值的方法,然后在實現(xiàn)中實現(xiàn)即可止毕。

3.6 迭代器模式的優(yōu)缺點

  • 更好的封裝性
  • 可以以不同的遍歷方式來遍歷一個聚合
  • 迭代器簡化了聚合的接口
  • 簡化客戶端調(diào)用
  • 同一個聚合上可以有多個遍歷

4.思考迭代器模式

4.1 迭代器模式的本質(zhì)

控制訪問聚合對象中的元素

4.2 何時選用

  • 1)如果你希望提供訪問一個聚合對象的內(nèi)容模蜡,但是又不想暴露它的內(nèi)部表示的時候,可以使用迭代器模式來提供迭代器接口滓技,從而讓客戶端只是通過迭代器的接口來訪問聚合對象哩牍,而無需關(guān)心聚合對象內(nèi)部實現(xiàn)。
  • 2)如果你希望有多種遍歷方式可以訪問聚合對象令漂,可以使用迭代器模式
  • 3)如果你希望為遍歷不同的聚合對象提供一個統(tǒng)一的接口膝昆,可以使用迭代器模式

4.3 翻頁迭代

在實際開發(fā)中很常用的翻頁功能的實現(xiàn),常見的翻頁功能有如下幾種實現(xiàn)方式:

  • 1)純數(shù)據(jù)庫實現(xiàn)依靠SQL提供的功能實現(xiàn)翻頁叠必,用戶每次請求翻頁的數(shù)據(jù)荚孵,就會到數(shù)據(jù)庫中獲取相應(yīng)的數(shù)據(jù)
  • 2)純內(nèi)存實現(xiàn)就是一次性從數(shù)據(jù)庫中把需要的所有數(shù)據(jù)都取出來放到內(nèi)存中,然后用戶請求翻頁時纬朝,從內(nèi)存中獲取相應(yīng)的數(shù)據(jù)
  • 3)上面兩種方式各有優(yōu)缺點:
    第一種方案明顯是時間換空間的策略收叶,每次獲取翻頁的數(shù)據(jù)都要訪問數(shù)據(jù)庫,運行速度相對比較慢共苛,而且很耗數(shù)據(jù)庫資源判没,但是節(jié)省內(nèi)存空間。
    第二種方案是典型的空間換時間隅茎,每次是直接從內(nèi)存中獲取翻頁的數(shù)據(jù)澄峰,運行速度快,但是很耗內(nèi)存辟犀。
  • 4)純數(shù)據(jù)庫實現(xiàn) + 純內(nèi)存實現(xiàn)
    思路是這樣的:如果每頁顯示10條記錄俏竞,根據(jù)判斷,用戶很少翻到10頁過
    后堂竟,那好了魂毁,第一次訪問的時候,就一次性從數(shù)據(jù)庫中獲取前10頁的數(shù)據(jù)出嘹,也就是100條記錄席楚,把這100條記錄放在內(nèi)存里面。
    這樣一來税稼,當(dāng)用戶在前10頁內(nèi)進行翻頁操作的時候烦秩,就不用再訪問數(shù)據(jù)庫了刁赦,而是直接從內(nèi)存中獲取數(shù)據(jù),這樣速度就快了闻镶。
    當(dāng)用戶想要獲取第11頁的數(shù)據(jù),這個時候才會再次訪問數(shù)據(jù)庫丸升,對于這個時候到底獲取多少頁的數(shù)據(jù)铆农,簡單的處理就是繼續(xù)獲取10頁的數(shù)據(jù),比較好的方式就是根據(jù)訪問統(tǒng)計進行衰減訪問狡耻,比如折半獲取墩剖,也就是第一次訪問數(shù)據(jù)庫獲取10頁的數(shù)據(jù),那么第二次就只獲取5頁夷狰,如此操作直到一次從數(shù)據(jù)庫中獲取一頁的數(shù)據(jù)岭皂。這也符合正常規(guī)律,因為越到后面沼头,被用戶翻頁到的機會也就越小了爷绘。

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市进倍,隨后出現(xiàn)的幾起案子土至,更是在濱河造成了極大的恐慌,老刑警劉巖猾昆,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陶因,死亡現(xiàn)場離奇詭異,居然都是意外死亡垂蜗,警方通過查閱死者的電腦和手機楷扬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贴见,“玉大人烘苹,你說我怎么就攤上這事∮叮” “怎么了螟加?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吞琐。 經(jīng)常有香客問我捆探,道長,這世上最難降的妖魔是什么站粟? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任黍图,我火速辦了婚禮,結(jié)果婚禮上奴烙,老公的妹妹穿的比我還像新娘助被。我一直安慰自己剖张,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布揩环。 她就那樣靜靜地躺著搔弄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丰滑。 梳的紋絲不亂的頭發(fā)上顾犹,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音褒墨,去河邊找鬼炫刷。 笑死,一個胖子當(dāng)著我的面吹牛郁妈,可吹牛的內(nèi)容都是我干的浑玛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼噩咪,長吁一口氣:“原來是場噩夢啊……” “哼顾彰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剧腻,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤拘央,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后书在,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灰伟,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年儒旬,在試婚紗的時候發(fā)現(xiàn)自己被綠了栏账。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡栈源,死狀恐怖挡爵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甚垦,我是刑警寧澤茶鹃,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站艰亮,受9級特大地震影響闭翩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迄埃,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一疗韵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧侄非,春花似錦蕉汪、人聲如沸流译。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽福澡。三九已至,卻和暖如春驹马,著一層夾襖步出監(jiān)牢的瞬間竞漾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工窥翩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鳞仙。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓寇蚊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棍好。 傳聞我的和親對象是個殘疾皇子仗岸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容