设计模式学习之迭代器模式(Iterator,行为型模式)(17)
参考地址:http://www.cnblogs.com/zhili/p/IteratorPattern.html
一、介绍
迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作也放在集合对象中,但这样的话,集合对象就承担太多的责任了,面向对象设计原则中有一条是单一职责原则,所以我们要尽可能地分离这些职责,用不同的类去承担不同的职责。迭代器模式就是用迭代器类来承担遍历集合元素的职责。
二、定义:
迭代器模式提供了一种方法顺序访问一个聚合对象(理解为集合对象)中各个元素,而又无需暴露该对象的内部表示,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
三、在.NET中实现迭代器模式
public class MyCollection : IEnumerable { private int[] items;//集合设置为私有,外部不可以访问,只暴露接口给外部访问 public MyCollection() { items = new int[] {1, 3, 4}; } //public IEnumerator GetEnumerator() //{ // return new MyEnumerator(this); //} //.net 2.0 中的Iterator public IEnumerator GetEnumerator() { for (int i = 0; i < items.Length; i++) { yield return items[i]; } } private class MyEnumerator : IEnumerator//私有内部类 { private int index; MyCollection collection; public MyEnumerator(MyCollection collection) { this.collection = collection; index = -1; } public bool MoveNext() { index++; return index < collection.items.Length; } public void Reset() { index = -1; } public object Current { get { return collection.items[index]; } } } } internal class Client { private static void Main(string[] args) { MyCollection col = new MyCollection(); foreach (int item in col) { Console.WriteLine(item); } //foreach 相当于以下代码 IEnumerator rator = col.GetEnumerator(); while (rator.MoveNext()) { Console.WriteLine(rator.Current.ToString()); } Console.ReadKey(); } }
四、.NET中迭代器模式的应用
在.NET下,迭代器模式中的聚集接口和迭代器接口都已经存在了,其中IEnumerator接口扮演的就是迭代器角色,IEnumberable接口则扮演的就是抽象聚集的角色,只有一个GetEnumerator()方法,关于这两个接口的定义可以自行参考MSDN。在.NET 1.0中,.NET 类库中很多集合都已经实现了迭代器模式,大家可以用反编译工具Reflector来查看下mscorlib程序集下的System.Collections命名空间下的类,这里给出ArrayList的定义代码,具体实现代码可以自行用反编译工具查看,具体代码如下所示:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable { // Fields private const int _defaultCapacity = 4; private object[] _items; private int _size; [NonSerialized] private object _syncRoot; private int _version; private static readonly object[] emptyArray; public virtual IEnumerator GetEnumerator(); public virtual IEnumerator GetEnumerator(int index, int count); // Properties public virtual int Capacity { get; set; } public virtual int Count { get; } ..............// 更多代码请自行用反编译工具Reflector查看 }
五、迭代器模式的适用场景
在下面的情况下可以考虑使用迭代器模式:
系统需要访问一个聚合对象的内容而无需暴露它的内部表示。
系统需要支持对聚合对象的多种遍历。
系统需要为不同的聚合结构提供一个统一的接口。
六、迭代器模式的优缺点
由于迭代器承担了遍历集合的职责,从而有以下的优点:
迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象。
迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作
迭代器模式存在的缺陷:
迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用foreach语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。