3.4設(shè)計模式之迭代器模式(Iterator)

3.4.1 模式意圖:

系統(tǒng)中會有對集合的元素進(jìn)行自增或者自減順序的訪問操作胀蛮,對于這種需求我們可以使用迭代器模式來建立對應(yīng)的迭代器,C#自帶的IEnumerator也是利用了這種模式的特點(diǎn)退腥。

3.4.2 模式概念:

它屬于行為型模式狡刘,提供一種方法困鸥,順序訪問聚合對象中的各個元素疾就,而又不暴露該對象的內(nèi)部表示。

3.4.3 模式元素:

  • 迭代器抽象(IIterator)
  • 迭代器細(xì)節(jié)(ConcreteIterator)
  • 需要迭代的集合(Group)

3.4.4 代碼示例:

下面筆者逐步完成迭代器模式的構(gòu)建鸟废。

創(chuàng)建一個簡單的集合侮攀。

    public class Group
    {
        private IList<object> items = new List<object>();
        public int Count
        {
            get { return items.Count; }
        }
        public object this[int index]
        {
            get { return items[index]; }
            set { items.Insert(index, value); }
        }
    }

為了讓多種集合都能使用同一種遍歷方式厢拭,我們再創(chuàng)建一個通用迭代器供鸠。

    public class ConcreteIterator
    {
        private IList<object> items = new List<object>();
        public Iterator(IList<object> tempItems)
        {
            items = tempItems;
        }
        private int index = -1;
        public object Current
        {
            get { return items[index]; }
        }
        public bool MoveNext()
        {
            return items.Count > ++index;
        }
        public void Reset()
        {
            index = -1;
        }
    }

然后把迭代器鑲嵌到這個集合中。

    public class Group
    {
        private IList<object> items = new List<object>();
        public int Count
        {
            get { return items.Count; }
        }
        public object this[int index]
        {
            get { return items[index]; }
            set { items.Insert(index, value); }
        }

        public ConcreteIterator GetIterator()
        {
            return new ConcreteIterator(items);
        }
    }

調(diào)用示例代碼薄坏。

    void Start()
    {
        Group group = new Group();
        group[0] = "愛";
        group[1] = "生";
        group[2] = "活";
        group[3] = "愛";
        group[4] = "海";
        group[5] = "瀾";

        Iterator iterator = group.GetIterator();

        while (iterator.MoveNext())
        {
            this.Log($"現(xiàn)在的元素為:{iterator.Current}");
        }
    }

開始重構(gòu)

Iterator中不能確定這個遍歷的集合是列表胶坠、字典還是數(shù)組沈善,但是可以確定他們都含有CurrentMoveNextReset三種元素闻牡,所以將這三種元素進(jìn)行抽象罩润,與原來的迭代器類進(jìn)行剝離。

    public interface IIterator
    {
        object Current { get; }
        bool MoveNext();
        void Reset();
    }

原迭代器類繼承接口IIterator金度。

    public class ConcreteIterator: IIterator
    {
        private IList<object> items = new List<object>();
        public Iterator(IList<object> tempItems)
        {
            items = tempItems;
        }
        private int index = -1;
        public object Current
        {
            get { return items[index]; }
        }
        public bool MoveNext()
        {
            return items.Count > ++index;
        }
        public void Reset()
        {
            index = -1;
        }
    }

既然原迭代器類繼承接口IIterator猜极,那么可以根據(jù)這個接口所規(guī)定的結(jié)構(gòu)祝峻,讓細(xì)節(jié)的實現(xiàn)統(tǒng)統(tǒng)轉(zhuǎn)移到子類中實現(xiàn),也就是說酬姆,我們可以定義出多種滿足不同迭代需求的迭代類辞色,但是調(diào)用的函數(shù)都是一樣的浮定。根據(jù)里氏替換原則可知,對應(yīng)的Group中所返回的public Iterator GetIterator()完全可以用接口IIterator代替立美。

    public class Group
    {
        private IList<object> items = new List<object>();
        public int Count
        {
            get { return items.Count; }
        }
        public object this[int index]
        {
            get { return items[index]; }
            set { items.Insert(index, value); }
        }

        public IIterator GetIterator()
        {
            return new ConcreteIterator(items);
        }
    }

最后建蹄,為了區(qū)分什么樣子的集合可以使用通用迭代模式裕偿,我們做一個獲得迭代器的接口,只要繼承這個接口的集合劲腿,就都可以使用通用迭代模式了鸟妙。

    public interface IEnumerable
    {
        ConcreteIterator GetIterator();
    }

    public class Group: IEnumerable
    {
        private IList<object> items = new List<object>();
        public int Count
        {
            get { return items.Count; }
        }
        public object this[int index]
        {
            get { return items[index]; }
            set { items.Insert(index, value); }
        }

        public IIterator GetIterator()
        {
            return new ConcreteIterator(items);
        }
    }

3.4.5 寫法對比:

3.4.6 模式分析:

經(jīng)過剝離和抽象,我們的迭代器模式就完成了垃瞧。迭代器就是把原有需要遍歷的結(jié)構(gòu)進(jìn)行一次包裝坪郭,把包裝后的結(jié)構(gòu)再統(tǒng)一進(jìn)行遍歷。

其實在C# 中自帶的迭代器要比我們這個更強(qiáng)大嗦锐,它最大的特點(diǎn)就是按需逐步查詢 Unity 之?dāng)?shù)據(jù)集合解析中的最后IEnumerable補(bǔ)充部分有例子說明沪曙,這里就不在熬述。

3.4.7 應(yīng)用場景:

需要按指定順序迭代查詢集合中的元素碳默。

3.4.8 小結(jié):

如果系統(tǒng)自帶的迭代器更好缘眶,就用系統(tǒng)的,這種無用的輪子我們還是不要浪費(fèi)時間再造了该抒,了解下原理就好顶燕。


更多設(shè)計模式詳見:設(shè)計模式全家桶

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欧引,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子芝此,更是在濱河造成了極大的恐慌惠爽,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件租副,死亡現(xiàn)場離奇詭異较性,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)责循,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門院仿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人剥汤,你說我怎么就攤上這事】愿遥” “怎么了鹿驼?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵畜晰,是天一觀的道長。 經(jīng)常有香客問我舷蟀,道長面哼,這世上最難降的妖魔是什么魔策? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任闯袒,我火速辦了婚禮,結(jié)果婚禮上政敢,老公的妹妹穿的比我還像新娘。我一直安慰自己唾那,他們只是感情好褪尝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著避诽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲤妥。 梳的紋絲不亂的頭發(fā)上轨功,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天容达,我揣著相機(jī)與錄音,去河邊找鬼羡滑。 笑死算芯,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的熙揍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼意系!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蛔添,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤夸溶,失蹤者是張志新(化名)和其女友劉穎凶硅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咏尝,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年扰才,在試婚紗的時候發(fā)現(xiàn)自己被綠了衩匣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥航。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡递雀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搜吧,到底是詐尸還是另有隱情杨凑,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布蜒程,位于F島的核電站昭躺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窍仰。R本人自食惡果不足惜氨肌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一阵翎、第九天 我趴在偏房一處隱蔽的房頂上張望劝枣。 院中可真熱鬧律罢,春花似錦婚陪、人聲如沸族沃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漓糙。三九已至昆禽,卻和暖如春蝇庭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哮内。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工漾根, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓从绘,卻偏偏與公主長得像僵井,于是被迫代替她去往敵國和親驳棱。 傳聞我的和親對象是個殘疾皇子批什,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 工資表數(shù)據(jù)的整合## 考慮這樣一個實際應(yīng)用:整合工資表數(shù)據(jù)。 這個項目的背景是這樣的社搅,項目...
    七寸知架構(gòu)閱讀 2,547評論 0 53
  • 鏈接:https://github.com/WiKi123/DesignPattern作者: WiKi123(gi...
    樹懶啊樹懶閱讀 3,511評論 0 2
  • --記一次奇妙的實習(xí)經(jīng)歷 有的人把日子過成了苦情詩 有的人天生演的就是輕喜劇 都說撐大男人胸懷靠的是委屈 卻不知驻债,...
    蝶舞cc閱讀 239評論 0 3
  • 早上醒來一次,之后就賴到中午才起床形葬。真希望假期每天能早點(diǎn)起來啊合呐,至少能干的事多一點(diǎn)(真不是在影射P5 下午專心把P...
    真晝之月閱讀 105評論 0 0