設計模式(十九)—迭代器模式(行為型)
一、簡介(Brief Introduction)
提供一種方法順序訪問一個聚合物件中各個元素,而又不需暴露該物件的內部表示
例子1:電視遙控器的頻道遍歷
二、模式分析(Analysis)
Iterator(迭代器):迭代器定義訪問和遍歷元素的介面
ConcreteIterator(具體迭代器):具體迭代器實現迭代器介面,對該聚合遍歷時跟蹤當前位置,跟蹤聚合中的當前物件,並能夠計算出待遍歷的後繼物件
Aggregate(聚合):聚合定義建立相應迭代器物件的介面
ConcreteAggregate(具體聚合):具體聚合實現建立相應迭代器的介面,該操作返回ConcreteIterator的一個適當的例項
三、案例分析(Example)
namespace 迭代器
{
1、客戶端
2、Itrator迭代器抽象類class Program { static void Main(string[] args) { ConcrteAggregate a = new ConcrteAggregate(); 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.Read(); } }
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
3、Aggregate聚集抽象類4、ConcreteAggregate具體聚集類,abstract class Aggregate { public abstract Iterator CreateIterator(); } //concreteIterator具體迭代器,繼承Iterator class ConcreteIterator : Iterator { private ConcrteAggregate aggregate; private int current = 0; public ConcreteIterator(ConcrteAggregate 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() { return current >= aggregate.Count ? true : false; } public override object CurrentItem() { return aggregate[current]; } }
class ConcrteAggregate : Aggregate
{
private IList <object > items=new List <object>();
public override 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 );}
}
}
}
四、解決的問題(What To Solve)
迭代器模式可用來:
• 訪問一個聚合物件的內容而無需暴露它的內部表示。
• 需要為聚合物件提供多種遍歷方式。
• 為遍歷不同的聚合結構提供一個統一的介面 (即, 支援多型迭代)
迭代器模式是與集合共生共死的,一般來說,我們只要實現一個集合,就需要同時提供這個集合的迭代器。假如我們要實現一個這樣的新的容器,當然也需要引入迭代器模式,給我們的容器實現一個迭代器。
但是,由於容器與迭代器的關係太密切了,所以大多數語言在實現容器的時候都給提供了迭代器,並且這些語言提供的容器和迭代器在絕大多數情況下就可以滿足我 們的需要,所以現在需要我們自己去實踐迭代器模式的場景還是比較少見的,我們只需要使用語言中已有的容器和迭代器就可以了。
五、優缺點(Advantage and Disadvantage)
優點:
1 )它支援以不同的方式遍歷一個聚合物件 : 複雜的聚合可用多種方式進行遍歷。迭代器模式使得改變遍歷演算法變得很容易 : 僅需用一個不同的迭代器的例項代替原先的例項即可。你也可以自己定義迭代器的子類以支援新的遍歷。
2) 迭代器簡化了聚合的介面有了迭代器的遍歷介面,聚合本身就不再需要類似的遍歷介面了。這樣就簡化了聚合的介面。
3) 在同一個聚合上可以有多個遍歷每個迭代器保持它自己的遍歷狀態。因此你可以同時進行多個遍歷。
4)在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有程式碼,滿足“開閉原則”的要求。
5)封裝性良好,使用者只需要得到迭代器就可以遍歷,而對於遍歷演算法則不用去關心。
缺點
由於迭代器模式將儲存資料和遍歷資料的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。對於比較簡單的遍歷(像陣列或者有序列表),使用迭代器方式遍歷較為繁瑣,大家可能都有感覺,像ArrayList,我們寧可願意使用for迴圈和get方法來遍歷集合。
六、擴充套件(Extend)
1)聚合是一個管理和組織資料物件的資料結構。
2)聚合物件主要擁有兩個職責:一是儲存內部資料;二是遍歷內部資料。
3)儲存資料是聚合物件最基本的職責。
4)將遍歷聚合物件中資料的行為提取出來,封裝到一個迭代器中,通過專門的迭代器來遍歷聚合物件的內部資料,這就是迭代器模式的本質。迭代器模式是“單一職責原則”的完美體現。
七、聯絡(Link)
Composite :迭代器常被應用到象複合這樣的遞迴結構上。
FactoryMethod:多型迭代器靠Factory Method來例化適當的迭代器子類。
Memento:常與迭代器模式一起使用。迭代器可使用一個 Memento來捕獲一個迭代的狀態。迭代器在其內部儲存Memento。
八、總結(Summary)
迭代器結合了封裝和多型的面向物件程式設計原理。使用迭代器,你可以對集合中的物件進行操作,而無需專門瞭解集合如何顯現或者集合包含什麼(物件的種 類)。迭代器提供了不同固定迭代實現的統一介面,它完全包含了如何操縱特定集合的詳細資訊,包括顯示哪些項(過濾)及其顯示順序(排序)。