- 迭代器模式
- 基于IEnumerable的實(shí)現(xiàn)
- 使用場(chǎng)景
- 迭代器模式的優(yōu)缺點(diǎn)
迭代器模式
迭代器模式用于順序訪問(wèn)集合對(duì)象的元素祠够,而不需要知道集合對(duì)象的底層表示命浴。Java和.Net等語(yǔ)言已經(jīng)將迭代器作為其內(nèi)部語(yǔ)法元素旋炒,比如在C#中掌测,集合對(duì)象只需要實(shí)現(xiàn)IEnumberable接口乖阵,然后就可以用foreach來(lái)遍歷了旅择。
迭代器模式提示我們要從使用者的角度考慮如何設(shè)計(jì)接口惭笑,如何對(duì)外提供訪問(wèn)內(nèi)部對(duì)象的方式。即便我們組織的對(duì)象系統(tǒng)內(nèi)部結(jié)構(gòu)很復(fù)雜生真,但對(duì)于客戶程序而言最簡(jiǎn)單的方式莫過(guò)于通過(guò)for /foreach循環(huán)依次遍歷沉噩,至于遍歷過(guò)程中的次序、分類篩選等則由目標(biāo)類型自己封裝汇歹。
GOF對(duì)迭代器模式描述為:
Provide a way to access the elements of an aggregate objectsequentially without exposing its underlying representation.
— Design Patterns : Elements of Reusable Object-Oriented Software
UML類圖:
代碼實(shí)現(xiàn)
//迭代器接口
public interface IIterator<T>
{
T Next();
bool HasNext();
}
//具體迭代器
public class ConcreteIterator<T> : IIterator<T>
{
private ConcreteAggretate<T> Aggretate; //成員變量屁擅,關(guān)聯(lián)關(guān)系
private int cursor = 0;
public ConcreteIterator(ConcreteAggretate<T> agg)
{
this.Aggretate = agg;
}
public bool HasNext()
{
return !(cursor >= Aggretate.Size);
}
public T Next()
{
if (HasNext())
{
return Aggretate.GetELement(cursor++);
}
else
{
return default(T);
}
}
}
//聚合接口
public interface IAggretate<T>
{
public void Add(T obj);
public void Remove(T obj);
public int Size { get; }
public T GetELement(int index);
public IIterator<T> GetIterator();
}
//具體聚合
public class ConcreteAggretate<T> : IAggretate<T>
{
private List<T> list = new List<T>(); //
public void Add(T obj)
{
list.Add(obj);
}
public void Remove(T obj)
{
list.Remove(obj);
}
public IIterator<T> GetIterator()
{
return new ConcreteIterator<T>(this); //在局部方法中new實(shí)例,屬依賴關(guān)系
}
public int Size
{
get
{
return list.Count;
}
}
public T GetELement(int index)
{
return list[index];
}
}
調(diào)用者代碼:
IAggretate<int> aggretate = new ConcreteAggretate<int>();
aggretate.Add(9);
aggretate.Add(8);
aggretate.Add(7);
IIterator<int> iterator = aggretate.GetIterator();
while (iterator.HasNext())
{
Console.WriteLine(iterator.Next());
}
基于IEnumerable的實(shí)現(xiàn)
以上便是經(jīng)典的迭代器模式的實(shí)現(xiàn)产弹,這種模式給聚合對(duì)象增加了一個(gè)創(chuàng)建其迭代器對(duì)象的方法派歌,迭代器的抽象定義和具體迭代器類型都作為一個(gè)額外的對(duì)象存在。
實(shí)際上C#已內(nèi)置了對(duì)迭代器模式的支持痰哨,只需要實(shí)現(xiàn)IEnumerable接口即可胶果,不再需要從0開(kāi)始,少了很多代碼量:
public class ConcreteAggretate<T> : IEnumerable<T>
{
private List<T> list = new List<T>();
public void Add(T obj)
{
list.Add(obj);
}
public void Remove(T obj)
{
list.Remove(obj);
}
public IEnumerator<T> GetEnumerator()
{
foreach (var item in list)
{
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
使用foreach遍歷IEnumerable接口
var aggretate = ConcreteAggretate<int>();
aggretate.Add(9);
aggretate.Add(8);
aggretate.Add(7);
foreach (var item in aggretate)
{
Console.WriteLine(item);
}
使用場(chǎng)景
- 對(duì)象內(nèi)部結(jié)構(gòu)比較復(fù)雜斤斧,為了讓調(diào)用者可以輕松地訪問(wèn)早抠,同時(shí)不需要暴露其內(nèi)部結(jié)構(gòu);
- 需要為聚合對(duì)象提供多種遍歷方式撬讽;
- 為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口蕊连;
迭代器模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 迭代器支持以不同的方式遍歷一個(gè)聚合對(duì)象,而且在同一個(gè)聚合上可以添加多個(gè)具有不同遍歷方式的迭代器游昼;
- 迭代器簡(jiǎn)化了聚合類的遍歷甘苍;
- 迭代器模式可以方便地增加新的聚合類和迭代器類,無(wú)須修改原有代碼烘豌。
缺點(diǎn)
迭代器模式通過(guò)將存儲(chǔ)數(shù)據(jù)和遍歷數(shù)據(jù)的職責(zé)分離载庭,為封裝集合地復(fù)雜性、隔離變化提供了極大的遍歷廊佩,但這種方式也有其固有的缺點(diǎn):每次
增加新的聚合類都需要對(duì)應(yīng)增加新的迭代器類囚聚,類的個(gè)數(shù)成對(duì)增加,這在一定程度上增加了系統(tǒng)的復(fù)雜性标锄。
參考書(shū)籍:
王翔著 《設(shè)計(jì)模式——基于C#的工程化實(shí)現(xiàn)及擴(kuò)展》