C#面向对象设计模式纵横谈 学习笔记18 Iterator迭代器模式(行为型模式)

本文介绍了迭代器模式的基本概念和在.NET中的实现方式。通过具体代码示例,展示了如何利用迭代器模式实现对集合对象的遍历,同时保持集合内部结构的隐藏。讨论了在不同.NET版本中实现迭代器模式的方法及其简化。

迭代器模式我们在平时的开发中应该经常用到。不直接使用也会间接使用,我们使用foreach语句来循环就是在间接的使用迭代器模式

迭代器就像指针一样可以向前向后移动,在.net中迭代器只能向后移动.

动机:
在软件的构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。

意图:
    提供一种方法顺序访问一个集合对象中的各个元素,而不暴露该对象的内部表示。

  1.  /// <summary>
  2.     /// 可迭代接口
  3.     /// </summary>
  4.     public interface IEnumerable
  5.     {
  6.         //得到迭代器
  7.         IEnumerator GetEnumerator();
  8.     }
  9.     
  10.     /// <summary>
  11.     /// 迭代器接口
  12.     /// </summary>
  13.     public interface IEnumerator
  14.     {
  15.         //得到当前的对象
  16.         object Current
  17.         {
  18.             get;
  19.         }
  20.         
  21.         bool MoveNext();
  22.         
  23.         void Reset();
  24.     }
  25.     /// <summary>
  26.     /// 集合类型,实现了可迭代接口
  27.     /// </summary>
  28.     public class MyCollection : IEnumerable
  29.     {
  30.         internal int[] items;
  31.         
  32.         public MyCollection()
  33.         {
  34.             items = new int[5] {1, 2, 3, 4, 5};
  35.         }
  36.         
  37.         #region IEnumerable 成员
  38.         //实现迭代接口,返回迭代器
  39.         public IEnumerator GetEnumerator()
  40.         {
  41.             //在这里进行解藕,将集合对象转换为迭代器
  42.             return new MyEnumerator(this);
  43.         }
  44.         #endregion
  45.     }
  46.     //迭代器对象,实现了迭代器接口
  47.     internal class MyEnumerator : IEnumerator
  48.     {
  49.     
  50.         private int nIndex;
  51.         MyCollection collection;
  52.         
  53.         //构造函数将集合类型转换成内部成员
  54.         public MyEnumerator(MyCollection coll)
  55.         {
  56.             this.collection = coll;
  57.             nIndex = -1;
  58.         }
  59.        
  60.         
  61.         #region IEnumerator 成员
  62.         
  63.         //返回当前迭代到的对象
  64.         public object Current
  65.         {
  66.             get
  67.             {
  68.                 return collection.items[nIndex];
  69.             }
  70.         }
  71.         //移动到下一个对象,指针向后移动
  72.         public bool MoveNext()
  73.         {
  74.             nIndex++;
  75.             
  76.             return (nIndex < collection.items.GetLength(0));
  77.         }
  78.         //重设迭代器,指针回零
  79.         public void Reset()
  80.         {
  81.             nIndex = -1;
  82.         }
  83.         #endregion
  84.     }

 

很清楚,在上面的代码中,我们通过GetEnumerator方法,将集合对象转换为了可迭代对象,这实际上是在对集合对象进行抽象,将他转换为迭代器。在这里,我们需要定义一个迭代器类,但是这是.net 1.1中的做法,在.net 2.0以后实现一个可迭代模式更加简单

  1.  /// <summary>
  2.     /// 集合类型,实现了可迭代接口
  3.     /// </summary>
  4.     public class MyCollection : IEnumerable<int>
  5.     {
  6.         internal int[] items;
  7.         
  8.         public MyCollection()
  9.         {
  10.             items = new int[5] {1, 2, 3, 4, 5};
  11.         }
  12.         #region IEnumerable<int> 成员
  13.         public IEnumerator<int> GetEnumerator()
  14.         {
  15.             for(int i = 0; i < items.Length; i++)
  16.             {
  17.                 yield return items[i];
  18.             }
  19.         }
  20.         #endregion
  21.         #region IEnumerable 成员
  22.         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  23.         {
  24.             for(int i = 0; i < items.Length; i++)
  25.             {
  26.                 yield return items[i];
  27.             }
  28.         }
  29.         #endregion
  30.     }

 

我们通过yield return关键字来返回一个IEnumerator接口,这个关键在在编译之后会自动生成对应的迭代器的代码。

在.net中迭代器只能先前,在c++中可以向后等其他操作。

注意:在迭代的过程中,我们不能向集合添加内容,后移除集合里的item,这样将会导致一些问题的出现

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值