动机(Motivation)
在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时让这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。
使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。
意图(Intent)
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
——《设计模式》GoF
示例代码
//.NET提供的迭代器抽象接口
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator
{
Object Current{get;}
bool MoveNext();
void Reset();
}
//实现
public class MyCollection:IEnumerable
{
int[] items;
public MyCollection()
{
items = new int[] {12,44,33,2,50};
}
public MyEnumerator GetEnumerator()
{
return new MyEnumerator(this);
}
public class MyEnumerator :IEnumerator
{
int nIndex;
MyCollection collection;
public MyEnumerator(MyCollection coll)
{
collection = coll;
nIndex = -1;
}
public bool MoveNext()
{
nIndex ++;
return (nIndex < collection.items.GetLength(0));
}
public int Current
{
get{return (collection.items[nIndex])};
}
public void Reset()
{
nIndex =-1;
}
}
}
public class MainClass
{
public static void Main()
{
MyCollection col = new MyCollection();
//foreach语句是C#对本模式的转化和内置
foreach(int i in col)
{
Console.WriteLine(i);
}
//foreach相当的代码
IEnumerator ietor = col.GetEnumerator();
while(ietor.MoveNext())
{
int i = (int) ietor.Current;
Console.WriteLine(i);
}
}
}
Iterator模式的几个要点
1)迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
2)迭代多态:为遍历不同的集合结构提供一个统一的接口,侧面支持不同的算法在不同的集合结构上进行操作。
3)迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构会导致问题。迭代是纯只读的,禁止更改结构(如删除元素)
.NET 2.0中Iterator的写法
public class MyCollection:IEnumerable
{
int[] items;
public MyCollection()
{
items = new int[] {12,44,33,2,50};
}
public IEnumerator GetEnumerator()
{
for (int i=0; i<5,i++)
{
yield return item[i];//只是写法不同,其实内部结构自动生成了。都是迭代器的模式
}
}
}