設(shè)計(jì)模式(17) 迭代器模式

  • 迭代器模式
  • 基于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類圖:

17.iterator.JPG

代碼實(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ò)展》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末顽铸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子料皇,更是在濱河造成了極大的恐慌跋破,老刑警劉巖簸淀,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓶蝴,死亡現(xiàn)場(chǎng)離奇詭異毒返,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)舷手,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)拧簸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人男窟,你說(shuō)我怎么就攤上這事盆赤。” “怎么了歉眷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵牺六,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我汗捡,道長(zhǎng)淑际,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任扇住,我火速辦了婚禮春缕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘艘蹋。我一直安慰自己锄贼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布女阀。 她就那樣靜靜地躺著宅荤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浸策。 梳的紋絲不亂的頭發(fā)上冯键,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音的榛,去河邊找鬼琼了。 笑死,一個(gè)胖子當(dāng)著我的面吹牛夫晌,可吹牛的內(nèi)容都是我干的雕薪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晓淀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼所袁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起凶掰,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤燥爷,失蹤者是張志新(化名)和其女友劉穎蜈亩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體前翎,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稚配,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了港华。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片道川。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖立宜,靈堂內(nèi)的尸體忽然破棺而出冒萄,到底是詐尸還是另有隱情,我是刑警寧澤橙数,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布尊流,位于F島的核電站,受9級(jí)特大地震影響灯帮,放射性物質(zhì)發(fā)生泄漏崖技。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一施流、第九天 我趴在偏房一處隱蔽的房頂上張望响疚。 院中可真熱鬧,春花似錦瞪醋、人聲如沸忿晕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)践盼。三九已至,卻和暖如春宾巍,著一層夾襖步出監(jiān)牢的瞬間咕幻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工顶霞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肄程,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓选浑,卻偏偏與公主長(zhǎng)得像蓝厌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子古徒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353