迭代器模式(Iterator),提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露該對象的內部表示。javascript
當你須要訪問一個彙集對象,並且無論這些對象是什麼都須要遍歷的時候,你就應該考慮用迭代器模式。同時,你須要對彙集有多重方式遍歷時們能夠考慮用迭代器模式。html
實際上,到目前爲止,迭代器的實用價值不大,由於不少高級編程語言,如C#,java等自己已經把這個模式作在語言中了,就是 foreach。另外想IEnumerable接口也是爲迭代器模式準備的。java
下面給出迭代器模式的UML示例圖:git
下面給出迭代器模式的代碼結構:編程
namespace ConsoleApplication1 { //Iterator迭代器抽象類 abstract class Iterator { public abstract object First(); //用於定義獲得開始對象、獲得下一個對象、判斷是否到結尾、當前對象等抽象方法統一接口 public abstract object Next(); public abstract bool IsDone(); public abstract object CurrentItem(); } //Aggregate彙集抽象類 abstract class Aggregate { public abstract Iterator CreateIterator(); //建立迭代器 } class ConcreteIterator : Iterator { private ConcreteAggregate aggregate; //定義了一個具體彙集對象 private int current = 0; public ConcreteIterator(ConcreteAggregate aggregate) { this.aggregate = aggregate; //初始化時將具體的彙集對象傳入 } public override object First() //獲得彙集的第一個對象 { return aggregate[0]; } public override object Next() //獲得彙集的下一個對象 { object ret = null; current++; if (current < aggregate.Count) { ret = aggregate[current]; } return ret; } public override bool IsDone() //判斷當前是否便利到結尾,到結尾則返回true { return current >= aggregate.Count ? true : false; } public override object CurrentItem() { return aggregate[current]; } } class ConcreteAggregate : Aggregate { private IList<object> items = new List<object>(); //聲明一個IList泛型變量,用於存放聚合對象。 public override Iterator CreateIterator() { return new ConcreteIterator(this); } public int Count { get { return items.Count; } //返回彙集總個數 } public object this[int index] //聲明一個索引器,對應items { get { return items[index]; } set { items.Insert(index, value); } } } class Program { static void Main(string[] args) { ConcreteAggregate a = new ConcreteAggregate(); a[0] = "大鳥"; a[1] = "小菜"; a[2] = "行李"; a[3] = "老外"; a[4] = "公交內部員工"; a[5] = "小偷"; Iterator i = new ConcreteIterator(a); object item = i.First(); while(!i.IsDone()) { Console.WriteLine("{0}請買車票!",i.CurrentItem()); i.Next(); } Console.ReadKey(); } } }
結果以下所示:設計模式
在以上的代碼中,爲何要有抽象的Iterator呢?由於可能會有多種對彙集的遍歷方式,這是就能夠實現此接口再從後倒序遍歷等的代碼。框架
以下,給出倒序遍歷的代碼:編程語言
增長一個類:ide
class ConcreteIteratorDesc : Iterator { private ConcreteAggregate aggregate; //定義了一個具體彙集對象 private int current = 0; public ConcreteIteratorDesc(ConcreteAggregate aggregate) { this.aggregate = aggregate; //初始化時將具體的彙集對象傳入 current = aggregate.Count - 1; } public override object First() //獲得彙集的第一個對象 { return aggregate[aggregate.Count - 1]; } public override object Next() //獲得彙集的下一個對象 { object ret = null; current--; if (current >= 0) { ret = aggregate[current]; } return ret; } public override bool IsDone() //判斷當前是否便利到結尾,到結尾則返回true { return current <0 ? true : false; } public override object CurrentItem() { return aggregate[current]; } }
同時客戶端中:post
//Iterator i = new ConcreteIterator(a); Iterator i = new ConcreteIteratorDesc(a);
這樣就是倒序遍歷了,這就是Iterator的區別。
以上是通常的迭代器模式,實際在.Net中是不用這麼麻煩的,由於.NET框架已經準備好了相關接口,只需實現就能夠了。
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //這個就是初學者代碼了,.Net默認的迭代器 IList<string> a = new List<string>(); a[0] = "大鳥"; a[1] = "小菜"; a[2] = "行李"; a[3] = "老外"; a[4] = "公交內部員工"; a[5] = "小偷"; foreach(string item in a) { Console.WriteLine("{0}請買票!",item); } Console.ReadKey(); } } }
在foreach裏,編譯器作了什麼呢?
IEnumerable<string> e = a.GetEnumerator(); while (e.MoveNext()) { Console.WriteLine("{0}請買車票!",e.Current); }
迭代器(Iterator)模式就是分離了集合對象的遍歷行爲,抽象出一個迭代器類來負責,這樣既能夠作到不暴露集合的內部結構,又可以讓外部代碼透明地訪問集合內部的數據。