65.9K
CodeProject 正在变化。 阅读更多。
Home

迭代器模式

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2008年10月2日

CPOL

2分钟阅读

viewsIcon

11351

迭代器模式的作用是提供一种按顺序访问聚合对象的方式,而无需了解聚合对象的内部结构。

引言

迭代器模式的作用是提供一种按顺序访问聚合对象的方式,而无需了解聚合对象的内部结构。
该模式在 C# 和 .NET Framework 中被广泛使用。我们拥有 IEnumeratorIEnumerable 接口来帮助我们为聚合对象实现迭代器。
当你实现自己的聚合对象时,应该实现这些接口来暴露一种遍历你的聚合对象的方式。

迭代器模式的应用场景

您应该在以下情况下使用该模式

  • 你需要一个统一的接口来遍历不同的聚合结构。
  • 你拥有多种遍历聚合结构的方式。 
  • 你不想暴露聚合对象的内部表示。

UML 图

C# 中的示例 

    #region Aggregate Item
    class AggregateItem
    {
        #region Properties
        /// <summary>
        /// The AggregateItem's data
        /// </summary>
        public string Data { get; set; }
        #endregion

        #region Ctor
        /// <summary>
        /// Construct a new AggregateItem with the given data
        /// </summary>
        /// <param name="data">The given data</param>
        public AggregateItem(string data)
        {
            Data = data;
        }
        #endregion
    }
    #endregion

    #region Aggregate Object
    interface Aggregate
    {
        Iterator GetIterator();
    }

    class AggregateImpl : Aggregate
    {
        #region Members
        private readonly List<AggregateItem> _aggregate;
        #endregion

        #region Properties
        /// <summary>
        /// The number of items in the aggregate
        /// </summary>
        public int Count
        {
            get
            {
                return _aggregate.Count;
            }
        }

        /// <summary>
        /// The indexer for the aggregate
        /// </summary>
        public AggregateItem this[int index]
        {
            get
            {
                return _aggregate[index];
            }
            set
            {
                _aggregate[index] = value;
            }
        }
        #endregion

        #region Ctor
        /// <summary>
        /// Construct a new AggregateImpl
        /// </summary>
        public AggregateImpl()
        {
            _aggregate = new List<AggregateItem>();
        }
        #endregion

        #region Aggregate Members
        /// <summary>
        /// Returns the Iterator for this aggregate object.
        /// </summary>
        /// <returns>Iterator</returns>
        public Iterator GetIterator()
        {
            return new IteratorImpl(this);
        }
        #endregion
    }
    #endregion

    #region Iterator
    interface Iterator
    {
        object First();
        object Next();
        bool IsDone();
        object Current();
    }

    class IteratorImpl : Iterator
    {
        #region Members
        private readonly AggregateImpl _aggregate;
        private int _nCurrentIndex;
        #endregion

        #region Iterator Members
        /// <summary>
        /// Return the first object of the iterator.
        /// </summary>
        /// <returns>First object of the iterator</returns>
        public object First()
        {
            return _aggregate[0];
        }

        /// <summary>
        /// Return the current object in the iterator and
        /// advance to the next one.
        /// </summary>
        /// <returns>The next object in the iterator</returns>
        public object Next()
        {
            object result = null;
            if (_nCurrentIndex < _aggregate.Count - 1)
            {
                result = _aggregate[_nCurrentIndex];

                _nCurrentIndex++;

            }

            return result;
        }

        /// <summary>
        /// Returns true if the iteration is done.
        /// </summary>
        /// <returns>True if the iteration is done</returns>
        public bool IsDone()
        {
            return _nCurrentIndex >= _aggregate.Count;
        }

        /// <summary>
        /// Return the current object in the iterator.
        /// </summary>
        /// <returns></returns>
        public object Current()
        {
            return _aggregate[_nCurrentIndex];
        }
        #endregion

        #region Ctor
        /// <summary>
        /// Construct a new IteratorImpl with the given aggregate.
        /// </summary>
        /// <param name="aggregate">The given aggregate</param>
        public IteratorImpl(AggregateImpl aggregate)
        {
            _nCurrentIndex = 0;
            _aggregate = aggregate;
        }
        #endregion
    }
    #endregion

示例中包含 5 名玩家。第一名玩家是一个聚合项,它是一个简单的数据结构。
我们还有一个聚合接口,它具有一个 GetIterator 方法,该方法返回迭代器。还有一个 Iterator 接口,它规定了迭代器的行为准则。我使用了这两个接口来实现一个聚合和一个迭代器。

IEnumerator 和 IEnumerable 接口

IEnumeratorIEnumerable 是在 C# 中实现迭代器模式的方式。
IEnumerable 接口暴露枚举器,支持对非泛型或泛型集合进行简单的迭代。它用于集合本身,以暴露枚举器的功能。IEnumerable 在 LINQ 中被广泛使用,并且是暴露 LINQ 功能的基础。
IEnumerator 接口支持对非泛型或泛型集合进行简单的迭代。
枚举器是一种只读方式来遍历集合。你应该使用这些接口来实现迭代器模式。它们的实现方式与
我之前提供的迭代器模式实现方式类似。 

简单的遍历示例 

虽然更倾向于使用 foreach 循环,但你可以使用 IEnumerator 接口遍历集合,如以下示例所示

    // build a new string list 
    var strList = new List<string>
                      {
                          "str1",
                          "str2",
                          "str3"
                      };

    // get list enumerator
    IEnumerator<string> enumerator = strList.GetEnumerator();

    // use the enumerator to traverse the list
    // and output the list's items to console
    string str;

    while (enumerator.MoveNext())
    {
        str = enumerator.Current;

        if (!string.IsNullOrEmpty(str))
        {
            Console.WriteLine("{0}", str);
        }
    } 

摘要

总而言之,即使我们不知道,我们也广泛地使用迭代器模式。每当你运行一个 foreach 循环时,迭代器模式都在底层被使用。

LINQ 扩展是基于 IEnumerable 接口构建的,它是 .NET Framework 中迭代器模式实现的一部分。

© . All rights reserved.