久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

利用C#實(shí)現(xiàn) Iterator 迭代器模式

 老馬的程序人生 2020-08-17

場景1

人物:大鳥,、小菜

這天是周末,,小菜和大鳥一早出門游玩兒,上了公交車,,車內(nèi)很擁擠,。

“上車的乘客請買票,。”售票員一邊在人縫中穿插著,,一邊說道,。

……

“先生,您這包行李太大了,,需要補(bǔ)票的,。”售票員對一位拿著大包行李的乘客說道,。

“哦,,這也需要買票呀,它又不是人,?!睅Т蟀欣畹某丝驼f。

“您可以看看規(guī)定,,當(dāng)您攜帶的行李占據(jù)了一個(gè)客用面積時(shí),,請?jiān)儋徺I同程車票一張,謝謝合作,?!笔燮眴T指了指車上的紙牌子。

這位乘客很不情愿地再買了一張票,。

“還有三位乘客沒有買票,,請買票!”

……

“這售票員夠厲害,,記得這么清楚,,上來幾個(gè)人都記得?!毙〔烁袊@道,。

“這也是業(yè)務(wù)能力的體現(xiàn)呀?!贝篪B解釋說,。

……

“先生請買票!”售票員對著一位老外說道,。

Sorry,,What do you say?”老外看來不會(huì)中文,。

“請買車票怎么說,?”售票員低聲的自言自語道,“Please buy……票怎么說……”。

ticket”小菜手掌放嘴邊,,小聲地提醒了一句,。

“謝謝,”售票員對小菜笑了笑,,接著用中國式英文對著老外說道,“Please buy ticket.

Oh,!yes.”老外急忙掏錢包拿了一張十元人民幣,。

“買票了,買票了,,還有兩位,,不要給不買票的人任何機(jī)會(huì)……”售票員找了老外錢后吆喝著,又對著一穿著同樣公交制服的女的說道,,“小姐,,請買票!”

“我也是公交公司的,,”這女的拿出一個(gè)公交證件,,在售票員面前晃了晃。

“不好意思,,公司早就出規(guī)定了,,工作證不得作為乘車憑證?!笔燮眴T說道,。

“我乘車從來就沒有買過票,憑什么在這就要買票,?!边@個(gè)乘客開始耍賴。

此時(shí)旁邊的乘客都來勁了,,七嘴八舌說起來,。

“公交公司的員工就不是乘客呀,國家總理來也要買票的,?!?/span>

“這人怎么這樣,想占大伙的便宜呀,?!?/span>

“你還當(dāng)過去呀,現(xiàn)在二十一世紀(jì)不吃大鍋飯了,。欠債還錢,,乘車買票,天經(jīng)地義……”

“行了行了,不就是一張票嗎,,搞什么搞,,吶!買票,?!边@不想買票的小姐終于扛不住了,遞出去兩元錢買了票,。

“還有哪一位沒有買票,,請買票?!笔燮眴T繼續(xù)在擁擠的車廂里跋涉著,。

“小偷!你這小偷,,把手機(jī)還我,。”突然站在小菜不遠(yuǎn)處的一個(gè)小姑娘對著一個(gè)猥瑣的男人叫了起來,。

“你不要亂講,,我哪有偷你的手機(jī),?!?/span>

“我看見你剛才把手伸進(jìn)了我的包里。就是你偷的,?!?/span>

“我沒有偷,,你看錯(cuò)了?!?/span>

“我明明看見你偷的,。”小姑娘急的哭了出來,。

小菜看不過去了,,“你的手機(jī)號多少,我?guī)湍愦虼蚩??!?/span>

138****8888”小姑娘像是看到了希望。

“哇,,這么強(qiáng)的號,,手機(jī)一定不會(huì)丟?!毙〔肆w慕著,,用自己的手機(jī)撥了這個(gè)號碼,。

那人眼看著不對,想往門口跑,,小菜和大鳥沖了上去,,一把按住他。

“你看,,我的手機(jī)響了,,就在他身上?!毙」媚锝辛似饋?,“就是他,他就是小偷,。”

此時(shí)兩個(gè)小伙已經(jīng)把猥瑣男死死按在地板上,。

“快打110報(bào)警,!”大鳥喊道。

此時(shí)公交車也停了下來,,所有的乘客都議論著“小偷真可惡”的話題,。

不一會(huì),民警來了,,問清楚了來由,,正準(zhǔn)備將小偷帶走時(shí),售票員對著小偷發(fā)話了:“慢著,,你是哪個(gè)沒有買票的人吧,?”

“啊,?嗯,!是的?!毙⊥狄荒樉趩驶卮鸬?。

“想走?,!可以,。先買票再說!”售票員干脆地說,。

小菜和大鳥對望一眼,,異口同聲道“強(qiáng)!”

……

場景2

人物:大鳥,、小菜

“小菜,,今天你真見到強(qiáng)人了吧,。”大鳥在下車后,,對小菜說道,。

“這個(gè)售票員,實(shí)在夠強(qiáng),,”小菜學(xué)著模仿道,,“想走?,!可以,。先買票再說!”

“這售票員其實(shí)在做一件重要的事,,就是把車廂里的所有人都遍歷一遍,,不放過一個(gè)不買票的乘客。這也是一個(gè)設(shè)計(jì)模式的體現(xiàn),?!?/span>

“大鳥,你也夠強(qiáng),,什么都可以往設(shè)計(jì)模式上套,,這也是模式?”

“當(dāng)然是模式,。這個(gè)模式就叫做迭代器模式,。”

迭代器模式(Iterator),,提供一種方法順序訪問一個(gè)聚合對象中各個(gè)元素,,而又不暴露該對象的內(nèi)部表示。

“你想呀,,售票員才不管你上來是人還是物(行李),,不管是中國人還是外國人,不管是不是內(nèi)部員工,,甚至哪怕是馬上要抓走的小偷,,只要是來乘車的乘客,就必須要買票,。同樣道理,,當(dāng)你需要一個(gè)聚合對象,而且不管這些對象是什么都需要遍歷的時(shí)候,,你就應(yīng)該考慮用迭代器模式,。另外,售票員可以從車頭到車尾來售票,,也可以從車尾向車頭來售票,,也就是說,,你需要對聚合有多種方式遍歷時(shí),可以考慮用迭代器模式,。由于不管乘客是什么,,售票員的做法始終是相同的,都是從第一個(gè)開始,,下一個(gè)是誰,,是否結(jié)束,當(dāng)前售到哪個(gè)人了,,這些方法每天她都在做,,也就是說,為遍歷不同的聚合結(jié)構(gòu)提供如開始,、下一個(gè),、是否結(jié)束、當(dāng)前哪一項(xiàng)等統(tǒng)一的接口,。

“聽你這么一說,,好像這個(gè)模式也不簡單哦?!?/span>

“哈,本來這個(gè)模式還是有點(diǎn)意思的,,不過現(xiàn)如今看迭代器模式實(shí)用價(jià)值遠(yuǎn)不如學(xué)習(xí)價(jià)值大了,,Martin Fowler甚至在自己的網(wǎng)站上提出撤銷此模式。因?yàn)楝F(xiàn)在高級編程語言如C#,、JAVA等本身已經(jīng)把這個(gè)模式做在語言中了,。”

 

Martin Fowler是國際著名的面向?qū)ο蠓治鲈O(shè)計(jì),、UML,、模式等方面的專家,敏捷開發(fā)方法的創(chuàng)始人之一,,他改變了人類開發(fā)軟件的模式,,他被開發(fā)者們尊稱為“教父”。現(xiàn)為ThoughtWorks公司的首席科學(xué)家,。

“哦,,是什么?”

“哈,,foreachin 你熟悉嗎,?”

“啊,原來是它,,沒錯(cuò)沒錯(cuò),,它就是不需要知道集合對象是什么,,就可以遍歷所有對象的循環(huán)工具,非常好用,?!?/span>

“另外還有像IEnumerable接口也是為迭代器模式而準(zhǔn)備的。不管如何,,學(xué)習(xí)一下GOF的迭代器模式的基本結(jié)構(gòu),,還是很有學(xué)習(xí)價(jià)值的。研究歷史是為了更好地迎接未來,。

 

DesignPatterns: Elements of Reusable Object-Oriented Software》(即后述《設(shè)計(jì)模式》一書),,由ErichGammaRichard Helm,、RalphJohnsonJohn Vlissides合著(Addison-Wesley,,1995)。這幾位作者常被稱為“四人組(Gangof Four,,GOF)”,。

迭代器實(shí)現(xiàn)

 

代碼見:Iterator _Level1

人物:大鳥、小菜

“看到?jīng)]有,,這就是我們的優(yōu)秀售票員售票——迭代器的整個(gè)運(yùn)作模式,。”

“大鳥,,你說為什么要有具體的迭代器ConcreteIterator來實(shí)現(xiàn)抽象的Iterator呢,?我感覺這里不需要抽象呀,直接訪問ConcreteIterator不是更好嗎,?”

“哈,,那是因?yàn)閯偛庞幸粋€(gè)迭代器的好處你沒有注意,當(dāng)你需要對聚集有多種方式遍歷時(shí),,可以考慮用迭代器模式,,事實(shí)上,售票員一定要從車頭到車尾這樣售票嗎,?”

“你意思是,,她可以從后向前遍歷?”

“當(dāng)然可以,,你不妨在寫一個(gè)實(shí)現(xiàn)從后往前的具體迭代器類看看,。”

代碼見:Iterator _Level2

.NET的迭代器實(shí)現(xiàn)

“剛才我們也說過,,實(shí)際使用當(dāng)中是不需要這么麻煩的,,因?yàn)?/span>.NET框架已經(jīng)為你準(zhǔn)備好了相關(guān)接口,你只需要去實(shí)現(xiàn)就好,?!?/span>

IEnumerable/ IEnumerable<T>用于創(chuàng)建枚舉類型,,相當(dāng)于迭代器模式的Aggregate(抽象類)。

    public interface IEnumerable

    {

        // 返回一個(gè)循環(huán)訪問集合的枚舉數(shù)

        IEnumerator GetEnumerator();

    }

    public interface IEnumerable<T> : IEnumerable

    {              

        // 返回一個(gè)循環(huán)訪問集合的枚舉數(shù)

        IEnumerator<T> GetEnumerator();

    }

注意:

1.泛型IEnumerable<T>接口與IEnumerable的非泛型版本很相似,。泛型版本從IEnumerable繼承,,所以也必須實(shí)現(xiàn)IEnumerable接口。

2.IEnumerable差不多,,泛型版本也包含了一個(gè)方法GetEnumerator,。然而,這個(gè)版本的GetEnumerator實(shí)現(xiàn)泛型IEnumerator<T>接口的類對象,。由于類必須實(shí)現(xiàn)兩個(gè)GetEnumerator方法,,我們需要顯式實(shí)現(xiàn)非泛型版本,并在類中實(shí)現(xiàn)泛型版本,。

3.一個(gè)Collection要支持foreach方式的遍歷,,必須實(shí)現(xiàn)IEnumerable接口(亦即,必須以某種方式返回IEnumerator object),。

4.IEnumerator object具體實(shí)現(xiàn)了Iterator(通過MoveNext(),,Reset()Current),。

5.從這兩個(gè)接口的用詞選擇上,,也可以看出其不同:IEnumerable是一個(gè)聲明式接口,聲明實(shí)現(xiàn)接口的class是“可枚舉(Enumerable)”的,,但并沒有說明如何實(shí)現(xiàn)枚舉器(Iterator),;IEnumerator是一個(gè)實(shí)現(xiàn)式接口IEnumerator object就是一個(gè)Iterator,。

6.IEnumeratorIEnumerable通過IEnumerableGetEnumerator()方法建立了鏈接,Client可以通過IEnumerableGetEnumerator()得到IEnumerator object,,在這個(gè)意義上,,將GetEnumerator()看作IEnumerator objectFactoryMethod也未嘗不可。

IEnumerator/ IEnumerator<T>枚舉數(shù),。相當(dāng)于迭代器模式的Iterator(抽象類),。


    public interface IEnumerator

    {

        // 返回序列中當(dāng)前位置項(xiàng)的屬性

        object Current { get;}

        // 將枚舉數(shù)推進(jìn)到集合下一個(gè)元素,。

        //方法返回值true表示迭代器成功前進(jìn)到集合中的下一個(gè)元素,,

        //返回false表示已經(jīng)位于集合的末尾。

        bool MoveNext();

        //恢復(fù)初始化指向的位置,,該位置位于集合中第一個(gè)元素之前

        void Reset();

}

    public interface IEnumerator<T>:IEnumerator,IDisposable

    {

        // 獲取集合中的當(dāng)前元素

        T Current { get; }

    }

注意:

1.IEnumerator是所有枚舉數(shù)的基接口,。IEnumerator<T>接口使用泛型來返回實(shí)際的類型,而不是object類型對象,。

2.由于IEnumeratorIEnumerator<T>都有一個(gè)叫做Current的成員,,我們應(yīng)該顯示實(shí)現(xiàn)IEnumerator版本,,然后在類中實(shí)現(xiàn)泛型版本。

3.枚舉數(shù)只允許讀取集合中的數(shù)據(jù),。枚舉數(shù)無法用于修改基礎(chǔ)集合,。這也是為什么說“不要在foreach循環(huán)中修改元素的原因”。

4.最初,,枚舉數(shù)被定位于集合中第一個(gè)元素的前面,。Reset也將枚舉數(shù)返回到此位置。在此位置,,調(diào)用Current會(huì)引發(fā)異常,。因此,在讀取Current的值之前,,必須調(diào)用MoveNext將枚舉數(shù)提前到集合的第一個(gè)元素,。

5.在調(diào)用MoveNextReset之前,Current返回同一對象,。MoveNextCurrent設(shè)置為下一個(gè)元素,。

6.在傳遞到集合的末尾之后,枚舉數(shù)放在集合中最后一個(gè)元素后面,,且調(diào)用MoveNext會(huì)返回False,。如果最后一次調(diào)用MoveNext返回False,則調(diào)用Current會(huì)引發(fā)異常,。若要再次將Current設(shè)置為集合的第一個(gè)元素,,可以調(diào)用Reset,然后再調(diào)用MoveNext,。

7.只要集合保持不變,,枚舉數(shù)就將保持有效。如果對集合進(jìn)行了更改(如添加,、修改或刪除元素),,則該枚舉數(shù)將失效且不可恢復(fù),并且下一次對MoveNextReset的調(diào)用將引發(fā)InvalidOperationExpression,。如果在MoveNextCurrent之間修改集合,,那么即使枚舉數(shù)已經(jīng)無效,Current也將返回它所設(shè)置成的元素,。

8.枚舉數(shù)沒有對集合的獨(dú)占訪問權(quán),;因此,枚舉一個(gè)集合在本質(zhì)上不是一個(gè)線程安全的過程,。甚至在對集合進(jìn)行同步處理時(shí),,其它線程仍可以修改該集合,這會(huì)導(dǎo)致枚舉數(shù)引發(fā)異常。若要在枚舉過程中保證線程安全,,可以在整個(gè)枚舉過程中鎖定集合,,或者捕獲由于其它線程進(jìn)行的更改而引發(fā)的異常。

我們已經(jīng)知道如何使用IEnumerableIEnumerator接口來創(chuàng)建可枚舉類型和枚舉數(shù),,但是這種方法有幾個(gè)缺點(diǎn),。

首先,由Current返回的對象是object類型的,。對于值類型而言,,在由current返回之前必須裝箱成object。在從Current獲取之后,,又必須再一次拆箱,。如果需要操作大量的數(shù)據(jù),會(huì)帶來嚴(yán)重的性能問題,。

非泛型接口方法的另外一個(gè)缺點(diǎn)是失去了類型安全,。值被作為對象來枚舉,所以可以是任何類型,。這就排除了編譯時(shí)的類型檢測,。

代碼見:ForeachSample02 – 非泛型枚舉數(shù)

代碼見:ForeachSample03 – 泛型枚舉數(shù)

“你會(huì)發(fā)現(xiàn),這兩個(gè)接口,,特別是IEnumerator要比我們剛才寫的抽象類Iterator要簡潔,,但可實(shí)現(xiàn)的功能卻一點(diǎn)不少,這其實(shí)也是對GOF的設(shè)計(jì)改良的結(jié)果,?!?/span>

“其實(shí)具體類實(shí)現(xiàn)這兩個(gè)接口的代碼也差別不大,是嗎,?”

“是的,,區(qū)別不大,另外這兩個(gè)接口還有相應(yīng)的泛型接口,?!?/span>

“有了這個(gè)基礎(chǔ),你再來看你最熟悉的foreach in 就很簡單了”,。

代碼見:Iterator _Level3

“這里用到了foreachin 而在編譯器里做了寫什么呢?其實(shí)它做的是下面的工作,?!?/span>

IEnumerator<string> e = lst.GetEnumerator();

e.Reset();

while(e.MoveNext())

{

    Console.WriteLine("{0}請買票!", e.Current);

}

“原來foreachin 就是實(shí)現(xiàn)這兩個(gè)接口來實(shí)現(xiàn)循環(huán)遍歷呀,?!?/span>

“是的,盡管我們不需要顯示的引用迭代器,,但系統(tǒng)本身還是通過迭代器來實(shí)現(xiàn)遍歷的,。總地來說,,迭代器(Iterator)模式就是分離了集合對象的遍歷行為,抽象出一個(gè)迭代器類來負(fù)責(zé),,這樣即可以做到不暴露集合的內(nèi)部結(jié)構(gòu),,又可讓外部代碼透明地訪問集合內(nèi)部的數(shù)據(jù)。迭代器模式在訪問數(shù)組,、集合,、列表等數(shù)據(jù)時(shí),尤其是數(shù)據(jù)庫數(shù)據(jù)操作時(shí),,有非常普遍的應(yīng)用,,但由于它太普遍了,所以各種高級語言都對它進(jìn)行了封裝,,所以反而給人感覺此模式本身不太常用了,。”


通過微信學(xué)習(xí)的知識(shí)只能是碎片化的知識(shí),,作為新時(shí)代的我們希望能夠構(gòu)建自己的知識(shí)結(jié)構(gòu),,使我們的知識(shí)體系化,系統(tǒng)化,,以后在遇到碎片化的知識(shí),,我們做的只是融合到自己的知識(shí)結(jié)構(gòu)中,故我們將推出“與LSGO一起學(xué)”系列課程,,幫助大家來構(gòu)建知識(shí)框架,,初步規(guī)劃有:

  1. “與LSGO一起學(xué)C++”;

  2. “與LSGO一起學(xué)C#”,;

  3. LSGO一起學(xué)Matlab”,;

  4. “與LSGO一起學(xué)數(shù)據(jù)結(jié)構(gòu)”;

  5. “與LSGO一起學(xué)設(shè)計(jì)模式”,;

  6. “與LSGO一起學(xué)可視化建模語言(UML)”,;

  7. “與LSGO一起學(xué)線性代數(shù)”;

  8. “與LSGO一起學(xué)高等數(shù)學(xué)”

  9. “與LSGO一起學(xué)概率論與數(shù)理統(tǒng)計(jì)”,;

  10. “與LSGO一起學(xué)抽象代數(shù),;

  11. “與LSGO一起學(xué)點(diǎn)集拓?fù)洹?/span>

  12. “與LSGO一起學(xué)數(shù)字圖像處理”;

  13. “與LSGO一起學(xué)智能計(jì)算”,;

如果對這些內(nèi)容感興趣,,可以一起來學(xué)習(xí)討論。

我們的官網(wǎng): www.lsgogroup.com

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多