周末,大鸟和小菜出门在公交上见到一个强人——强悍的售票员,不管是人是物,是中国人还是外国人,是内部员工还是小偷,只要你是来乘车的都逃不过售票员的法眼,都必须买票。这让大鸟又想起一种设计模式——迭代器模式,小菜也因此又学了一手。
【知识点】
1、概念
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应考虑使用迭代器模式。就如 大鸟和小菜遇到的售票员,不管你是人或物,只要符合乘车收费的标准都要遍历一遍收费。
2、模式角色
a.Aggregate(聚集抽象类):一个接口,创建相应迭代器对象的接口。
b.ConcreteAggregate(具体聚集类):具体聚集实现创建相应迭代器的接口,该操作返回ConcreteIterator 的一个适当的实例。
c.Iterator(迭代抽象类):一个接口,规定了遍历具体聚集的方法,比如First()和Next()方法。
d.ConcreteIterator(具体迭代器):继承Iterator,具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置。
迭代器模式结构图:
3、作用
访问一个聚合对象的内容而无需暴露它的内部表示
支持对聚合对象的多种遍历
为遍历不同的聚合结构提供一个统一的接口
4、代码实现
namespace Iterator
{
//Iterator迭代器抽象类
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
//Aggregate聚集抽象类
abstract class Aggregate
{
//创建迭代器
public abstract Iterator CreateIterator();
}
//ConcreteIterator具体迭代器类,继承Iterator
class ConcreteIterator : Iterator
{
//定义一个具体的聚集对象
private ConcreteAggregate aggregate;
private int current = 0;
//初始化时将具体的聚集对象传人
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
//得到聚集的第一个对象
public override object First()
{
return aggregate[0];
}
//得到聚集的下一个对象
public override object Next()
{
object ret = null;
current++;
if (current < aggregate.Count)
{
ret = aggregate[current];
}
return ret;
}
//判断当前是否遍历到结尾,到结尾返回true
public override bool IsDone()
{
return current >= aggregate.Count ? true : false;
}
//返回当前的聚集对象
public override object CurrentItem()
{
return aggregate[current];
}
}
//ConcreteAggregate具体聚集类
class ConcreteAggregate : Aggregate
{
private IList<object> items = new List<object>();
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
//返回聚集个数
public int Count
{
get { return items.Count; }
}
//声明一个索引器
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
}
}
namespace Iterator //迭代器模式
{
class Program
{
//客户端
static void Main(string[] args)
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "大鸟";
a[1] = "小菜";
a[2] = "行李";
a[3] = "老外";
a[4] = "小偷";
Iterator i = new ConcreteIterator(a);
object item = i.First();
while(!i.IsDone())
{
Console.WriteLine("{0}请买车票!", i.CurrentItem());
i.Next();
}
Console.Read();
}
}
}
运行结果:
5、发展
现如今迭代器模式的实用价值远没有学习价值大,原因在于现在的高级语言如C#等已经把这个模式做在语言中了。像foreach in就是不需要知道集合对象是什么,就可以遍历所有的对象的循环工具,简单好用,还有IEnumerable接口也是为迭代器模式而准备的。在实际使用中不用使用迭代器模式比较麻烦,在.NET框架中已经准备好了相关接口,看一下.NET的迭代器的代码实现:
namespace Iterator.NET
{
public interface IEumerator
{
object Current //获取集合中的当前元素
{
get;
}
bool MoveNext(); //将枚举数推进到集合的下一个元素
void Reset(); //恢复初始化指向位置,位于集合中第一个元素之前
}
public interface IEnumerable
{
IEumerator GetEnumerator(); //返回一个循环访问集合的枚举数
}
}
客户端代码
static void Main(string[] args)
{
IList<string> a = new List<string>();
a.Add("大鸟");
a.Add("小菜");
a.Add("行李");
a.Add("老外");
a.Add("小偷");
foreach(string item in a)
{
Console.WriteLine("{0}请买票!", item);
}
Console.Read();
}
运行结果:
【小结】
迭代器(Iterator)模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部数据。由于是非常普遍的应用所以各种高级语言都对其进行了封装,所以此模式变得不太常用。但是迭代器模式还是很具有学习价值的,所以更要认真的学习一下。用大鸟的话说就是“研究历史是为了更好地迎接未来”,为了未来要好好学习。