文章目錄
Gof定義
提供一種方法順序訪問一個彙總對象中的各個元素, 而又不暴露該對象的內部表示。
動機
在軟體構建過程中,集合對象內部結構常常變化各異。但對於這些集合對象,我們希望在不暴露其內部結構的同時,可以讓外部客戶代碼透明地訪問其中包含的元素;同時這種“透明遍曆”也為“同一種演算法在多種集合對象上進行操作”提供了可能。使用物件導向技術將這種遍曆機制抽象為“迭代器對象”為“應對變化中的集合對象”提供了一種優雅的方式。
迭代器模式結構圖:
Aggregate:集合結構介面
Iterator:迭代器介面
Concreteaggregate:集合結構的具體類,繼承Aggregate介面
ConcreteIteator:具體的迭代器類
代碼實現:
/// <summary>/// 集合結構介面/// </summary>public interface Aggregate{ Iterator CreateIterator();}/// <summary>/// 迭代器介面/// </summary>public interface Iterator{ object First(); object Next(); bool IsDone(); object CurrentItem();}/// <summary>/// 集合結構的具體類/// </summary>class ConcreteAggregate : Aggregate{ private List<object> items = new List<object>(); public Iterator CreateIterator() { return new ConcreteIterator(this); } public int Count { get { return items.Count; } } public object this[int index] { get { return items[index]; } set { items.Insert(index, value); } }}/// <summary>/// 具體的迭代器類/// </summary>class ConcreteIterator : Iterator{ private ConcreteAggregate _aggregate; private int _current = 0; public ConcreteIterator(ConcreteAggregate aggregate) { this._aggregate = aggregate; } public object First() { return _aggregate[0]; } public object Next() { object r = null; _current++; if (_current < _aggregate.Count) { r = _aggregate[_current]; } return r; } public bool IsDone() { return _current >= _aggregate.Count ? true : false; } public object CurrentItem() { return _aggregate[_current]; }}/// <summary>/// 用戶端調用/// </summary>class Program{ static void Main(string[] args) { ConcreteAggregate ca = new ConcreteAggregate(); ca[0] = "AspNet3.5 揭秘"; ca[0] = "重構:改善既有代碼的設計"; ca[2] = "設計模式"; ca[3] = "人月神話"; ca[4] = "代碼大全2"; Iterator i = new ConcreteIterator(ca); while (!i.IsDone()) { Console.WriteLine("要讀的書:" + i.CurrentItem()); i.Next(); } }}
上面的代碼是根據結構圖實現的基礎代碼,在設計的運用中可以使用Net架構給我們提供的相關介面IEnumerable和IEnumerator,這兩個介面在Net中的實現代碼如下:
public interface IEnumerable{ IEmumerator GetEnumerator();}public interface IEmumerator{ Object Current { get; } bool MoveNext(); void Reset();}
在Net中List實現了IEnumerable介面,下面的代碼將List作為資料的容器來實現遍曆:
class Program{ static void Main(string[] args) { List<string> list = new List<string> { "AspNet3.5 揭秘","重構:改善既有代碼的設計","設計模式", "人月神話","代碼大全2" }; IEnumerator i = list.GetEnumerator(); while (i.MoveNext()) { Console.WriteLine("要讀的書:" + i.Current); } }}
上面的代碼中試調用List的GetEnumerator方法返回IEmumerator類型的集合,然後取遍曆,這樣仍然顯得比較麻煩,其實在Net中foreach已經實現了這樣的功能,代碼如下:
class Program{ static void Main(string[] args) { List<string> list = new List<string> { "AspNet3.5 揭秘","重構:改善既有代碼的設計","設計模式", "人月神話","代碼大全2" }; foreach (string s in list) { Console.WriteLine("要讀的書:" + s); } }}
可以看出foreach其實就是實現了下面這段代碼
IEnumerator i = list.GetEnumerator();while (i.MoveNext()){ Console.WriteLine("要讀的書:" + i.Current);}Iterator模式的幾個要點
返回開篇(索引)