迭代器模式是GOF23种模式中的一种,目的是为了提供对集合的遍历。为什么要实现迭代器模式:
假设存在一个数组,我们的遍历模式可能是采用依据索引来进行遍历。又假设存在一个HashTable,我们的遍历模式就可能按照键值来进行遍历。无论是哪个集合,如果它们的遍历没有一个公共的接口,那么我们的客户端进行调用的时候,相当于是对具体类型进行了编码。这样以来,当需求变化的时候,就必须修改我们的代码。并且,由于客户端代码过多的关注了集合的内部实现,代码的可移植性就会变得很差,这直接违反了面向对象中的开闭原则。于是,迭代器模式就诞生了。现在,不要管FCL中是如何实现该模式的,我们先来实现一个我们自己的迭代器模式。
代码清单:
public class Program { static void Main(string[] args) { //使用接口IMyEnumerable代替MyList IMyEnumerable list = new MyList(); //得到迭代器,在循环中针对迭代器编码,而不是集合MyList IMyEnumerator enumerator = list.GetEnumerator(); for (int i = 0; i < list.Count; i++) { object current = enumerator.Current; enumerator.MoveNext(); } while (enumerator.MoveNext()) { object current = enumerator.Current; } } }
/// <summary> /// 要求所有的迭代器全部实现该接口 /// </summary> interface IMyEnumerator { bool MoveNext(); object Current { get; } }
/// <summary> /// 要求所有的集合实现该接口 /// 这样一来,客户端可以针对该接口编码,而无需关注具体的实现 /// </summary> interface IMyEnumerable { IMyEnumerator GetEnumerator(); int Count { get; } } class MyList : IMyEnumerable { object[] items = new object[10]; public IMyEnumerator MyEnumerator { get; set; } public object this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public IMyEnumerator GetEnumerator() { if (MyEnumerator == null) { return new MyEnumerator(this); } return MyEnumerator; } }
class MyEnumerator : IMyEnumerator { int index = 0; MyList myList; public MyEnumerator(MyList myList) { this.myList = myList; }
public bool MoveNext() { if (index + 1 > myList.Count) return false; else { index++; return true; } } public object Current { get { return myList[index]; } }
} |
MyList模拟了一个集合类,它继承了接口IMyEnumerable,这样,在客户端进行调用的时候,我们就可以直接使用IMyEnumerable来进行声明变量,如代码中的:
IMyEnumerable list = new MyList(); |