迭代器模式





5.00/5 (2投票s)
迭代器模式的作用是提供一种按顺序访问聚合对象的方式,而无需了解聚合对象的内部结构。
引言
迭代器模式的作用是提供一种按顺序访问聚合对象的方式,而无需了解聚合对象的内部结构。
该模式在 C# 和 .NET Framework 中被广泛使用。我们拥有 IEnumerator
和 IEnumerable
接口来帮助我们为聚合对象实现迭代器。
当你实现自己的聚合对象时,应该实现这些接口来暴露一种遍历你的聚合对象的方式。
迭代器模式的应用场景
您应该在以下情况下使用该模式
- 你需要一个统一的接口来遍历不同的聚合结构。
- 你拥有多种遍历聚合结构的方式。
- 你不想暴露聚合对象的内部表示。
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 接口
IEnumerator
和 IEnumerable
是在 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 中迭代器模式实现的一部分。