码迷,mamicode.com
首页 > 其他好文 > 详细

Iterator - 迭代器模式

时间:2017-03-15 12:11:05      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:image   构造函数   sum   范围   pre   alt   append   没有   指定   

Iterator - 迭代器模式

目录

 

简介

  这是一包奥利奥(数组),里面藏了很多块奥利奥饼干(数组中的元素),我将它们放在一个碟子上慢慢排好,从上往下一块块的拿起来(迭代),再一口气吃掉,这就是今天的早餐,也就是要说的 Iterator - 迭代器模式。

技术分享技术分享

 

 

回顾

  我们常用的 for 和 foreach,其实就是 MS 给我们封装后的迭代器模式。为什么数组和集合能够使用这两个关键字呢?因为他们都实现了一个接口 IEnumerable,实现了内部方法 GetEnumerator。我们对一个集合,或者是数组进行遍历的同时,也就是数组或集合元素的下标不断递增的一个过程。

技术分享

  左边的下标 0 表示数组的第一个元素;

  左边的下标 1 表示数组的第二个元素;

  ... ...

  左边的下标 i 表示数组的第i+1个元素;

  最后一个元素就是数组的长度 - 1;

  

 UML 类图

技术分享

 图

技术分享

 

代码分析

   IEnumerable 接口

    interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }

  这里只有一个方法 GetEnumerator(),该方法可以生成一个遍历集合的元素的迭代器。通过该迭代器,就可以进行集合元素的遍历了。

 

  IEnumerator 接口

    interface IEnumerator
    {
        bool MoveNext();

        object GetCurrent();
    }

  实现该接口的实例可以成为迭代器。这里有两个方法: MoveNext(),GetCurrent()。

  MoveNext():移动到下一个元素的下标,如果存在该下标(没有超出索引位置),则返回 true。

  GetCurrent():获取当前集合元素的值。

 

  Dish 类

    class Dish : IEnumerable
    {
        private readonly List<Aoliao> _aoliaos;

        public Dish()
        {
            _aoliaos = new List<Aoliao>();
        }

        public IEnumerator GetEnumerator()
        {
            return new DishIterator(this);
        }

        public void AppendAoliao(Aoliao aoliao)
        {
            _aoliaos.Add(aoliao);
        }

        public int GetCount()
        {
            return _aoliaos.Count;
        }

        public Aoliao GetAoliao(int index)
        {
            if (index >= GetCount())
            {
                throw new IndexOutOfRangeException();
            }

            return _aoliaos[index];
        }
    }

  这是一个碟子类,你可以把它抽象为集合,用于放置拆开后的奥利奥饼干。

  这里的构造函数,进行对 List<Aoliao> 进行集合的初始化。

  AppendAoliao(Aoliao aoliao):在原有的集合中追加新元素,在放置好的奥利奥饼干后再添加一块新的奥利奥饼干。

  GetCount():获取集合的个数,获取碟子上奥利奥饼干的总个数。

  GetAoliao(int index):根据下标获取集合中的元素。

 

   DishIterator.cs 类

    class DishIterator : IEnumerator
    {
        private int _index;
        private readonly Dish _dish;

        public DishIterator(Dish cookie)
        {
            _index = -1;
            _dish = cookie;
        }

        public bool MoveNext()
        {
            _index++;
            return _index < _dish.GetCount();
        }

        public object GetCurrent()
        {
            try
            {
                return _dish.GetAoliao(_index);
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }

  该类实现了 IEnumerator 接口,作为迭代器的一个实例对象,这里有两个字段:

  _index:用于指定数组元素的下标,递增,注意,这里我选择让下标从 -1 开始。

  _dish:保存对 Dish 类的一个引用。

  MoveNext():移动到下一个元素的下标,递增下标 _index,假如索引超出界限则返回 false。

  GetCurrent():获取当前元素,根据下标 _index。

 

  Aoliao.cs 类

    class Aoliao
    {
        /// <summary>
        /// 味道
        /// </summary>
        public bool Taste { get; set; }
    }

  这里的 Taste 属性,我只用于标识它是否好吃。

  

  Main.cs 类

    class Program
    {
        static void Main(string[] args)
        {
            var dish = new Dish();
            dish.AppendAoliao(new Aoliao() { Taste = true });
            dish.AppendAoliao(new Aoliao() { Taste = true });
            dish.AppendAoliao(new Aoliao() { Taste = true });

            var iterator = dish.GetEnumerator();
            while (iterator.MoveNext())
            {
                var aoliao = (Aoliao)iterator.GetCurrent();
                Console.WriteLine("味道: " + aoliao.Taste);
            }

            Console.Read();
        }
    }

技术分享

 

  dish 作为一个数组,在一开始初始化的时候放置几块奥利奥饼干,通过 GetEnumerator() 得到迭代器,在 while 循环中,通过 MoveNext() 移动到集合的下一个元素下标,直到超出索引范围,这就是之前为什么我将 DishIterator 的下标(_index)初始化值为 -1,。MoveNext() 方法会先移动光标的位置,再从迭代器的 GetCurrent() 方法取出当前元素的值(根据 MoveNext() 移动的下标)。

 

抽象的 UML 类图

技术分享

技术分享

 

Iterator - 迭代器模式

标签:image   构造函数   sum   范围   pre   alt   append   没有   指定   

原文地址:http://www.cnblogs.com/liqingwen/p/6550794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!