日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

[C# 设计模式] Iterator - 迭代器模式:我与一份奥利奥早餐的故事

發布時間:2025/3/17 C# 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [C# 设计模式] Iterator - 迭代器模式:我与一份奥利奥早餐的故事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Iterator - 迭代器模式

?

目錄

  • 前言
  • 回顧
  • UML 類圖
  • 代碼分析
  • 抽象的 UML 類圖
  • 思考

?

前言

  這是一包奧利奧(數組),里面藏了很多塊奧利奧餅干(數組中的元素),我將它們放在一個碟子上慢慢排好,從上往下一塊塊的拿起來(迭代),再一口氣吃掉,這就是今天的早餐,也就是要說的?Iterator - 迭代器模式。

?

?

回顧

  我們常用的 for 和 foreach,其實就是 MS 給我們封裝后的迭代器模式。為什么數組和集合能夠使用這兩個關鍵字呢?因為他們都實現了一個接口 IEnumerable,實現了內部方法?GetEnumerator。我們對一個集合,或者是數組進行遍歷的同時,也就是數組或集合元素的下標不斷遞增的一個過程。

  左邊的下標?0 表示數組的第一個元素;

  左邊的下標 1 表示數組的第二個元素;

  ... ...

  左邊的下標 i 表示數組的第i+1個元素;

  最后一個元素就是數組的長度 - 1;

  

?UML 類圖

?圖

?

代碼分析

?  IEnumerable 接口

interface IEnumerable{IEnumerator GetEnumerator();}

  這里只有一個方法?GetEnumerator(),該方法可以生成一個遍歷集合的元素的迭代器。通過該迭代器,就可以進行集合元素的遍歷了。

?

  IEnumerator 接口

interface IEnumerator{bool MoveNext();object GetCurrent();}

  實現該接口的實例可以成為迭代器。這里有兩個方法: MoveNext(),GetCurrent()。

  MoveNext():移動到下一個元素的下標,如果存在該下標(沒有超出索引位置),則返回 true。主要用于終止循環條件。

  GetCurrent():獲取當前集合元素的值,不過這里因為返回的類型為 object,可能需要進行強轉,當然,你也可以選擇使用泛型。

?

  Dish.cs 類(碟子)

class Dish : IEnumerable{private readonly List<Aoliao> _aoliaos;public Dish(){_aoliaos = new List<Aoliao>();}public IEnumerator GetEnumerator(){return new DishIterator(this);}public void AppendAoliao(Aoliao aoliao){_aoliaos.Add(aoliao);}public int GetCount(){return _aoliaos.Count;}public Aoliao GetAoliao(int index){if (index >= GetCount()){throw new IndexOutOfRangeException();}return _aoliaos[index];}}

  這是一個碟子類,因為它實現了 IEnumerable 接口,我把它當作集合,用于放置拆開包裝后的奧利奧餅干。

  這里的構造函數,進行對 List<Aoliao> 進行集合的初始化。

  AppendAoliao(Aoliao aoliao):在原有的集合中追加新元素,在放置好的奧利奧餅干后再添加一塊新的奧利奧餅干。

  GetCount():獲取集合的個數,獲取碟子上奧利奧餅干的總個數。

  GetAoliao(int index):根據下標獲取集合中的元素。

?

?  DishIterator.cs 類(碟子迭代器)

class DishIterator : IEnumerator{private int _index;private readonly Dish _dish;public DishIterator(Dish cookie){_index = -1;_dish = cookie;}public bool MoveNext(){_index++;return _index < _dish.GetCount();}public object GetCurrent(){try{return _dish.GetAoliao(_index);}catch (IndexOutOfRangeException){throw new InvalidOperationException();}}}

  該類實現了 IEnumerator 接口,作為迭代器的一個實例對象,用于遍歷?Dish 對象內集合的一個迭代器對象,這里有兩個字段:

  _index:用于指定數組元素的下標,遞增,注意,這里我選擇讓下標從 -1 開始。

  _dish:保存對 Dish 類的一個引用。

  MoveNext():移動到下一個元素的下標,遞增下標 _index,假如索引超出界限則返回 false,從這里可以得知奧利奧餅干有沒有吃完。

  GetCurrent():獲取當前元素,根據下標 _index。

?

  Aoliao.cs 類(奧利奧餅干)

class Aoliao{/// <summary>/// 味道/// </summary>public bool Taste { get; set; }}

  這里的?Taste 屬性,我只用于標識它是否好吃。

  

  Main.cs 類

class Program{static void Main(string[] args){var dish = new Dish();dish.AppendAoliao(new Aoliao() { Taste = true });dish.AppendAoliao(new Aoliao() { Taste = true });dish.AppendAoliao(new Aoliao() { Taste = true });var iterator = dish.GetEnumerator();while (iterator.MoveNext()){var aoliao = (Aoliao)iterator.GetCurrent();Console.WriteLine("味道: " + aoliao.Taste);}Console.Read();}}

?

  dish 作為一個數組,在一開始初始化的時候放置幾塊奧利奧餅干,通過?GetEnumerator() 可以得到迭代器,在 while 循環中,通過 MoveNext() 可以移動到集合的下一個元素下標,并取出奧利奧餅干,直到超出索引范圍(即奧利奧餅干已經吃完)才會終止循環。這就是之前為什么我將?DishIterator 的下標(_index)初始化值為 -1,MoveNext() 方法會先移動光標的位置,再從迭代器的?GetCurrent() 方法取出當前元素的值(根據 MoveNext()?移動后的下標)。

?

抽象的 UML 類圖

?

思考

  【1】為什么要使用 Iterator 迭代器模式呢?對于集合,或者數組,我們直接使用 for 和 foreach 不就可以了嗎?

  觀察上述代碼,我們發現在 while 循環內只涉及方法 MoveNext() 和 GetCurrent(),不依賴集合本身的?Dish 類對象,在遍歷時與集合沒有強耦合的關系,遍歷和實現進行了分離。

  也就是說,無論集合 Dish 本身如何變化,只要能夠正常返回 iterator 迭代器,我們就可以正常遍歷。

  設計模式的作用就是幫助我們編寫可復用的類。所謂“可復用”,是指將類當成“組件”,當一個組件發生變化時,會盡可能的減少對其他組件的影響,其他組件只需更少的修改或者不需要修改就可以繼續正常工作。

  

  【2】為什么我們有?ConcreteEnumerable 和?ConcreteIterator 兩個具體類,還要額外創建一層接口呢?

  我們總是幻想著使用實體類來解決遇到的所有問題。如果只使用具體類來解決問題,很容易增加類之間的強耦合度,這部分類也難以當成組件多次利用。為了降低類之間的耦合度,為了增加類的利用度,從而引入了抽象類和接口。

?

?  【總結】優先使用抽象類和接口來進行編程,而不要總想著采用具體類來實現編程。

?

?


【博主】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/6550794.html?

?

總結

以上是生活随笔為你收集整理的[C# 设计模式] Iterator - 迭代器模式:我与一份奥利奥早餐的故事的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。