场景:分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。
结构图:
看了这个图,你可能晕了,我也说这是见过目前第二复杂的设计模式,这个模式在C#中其实已经实现。比如foreach。我们肯定知道foreach的简便的语法了。
这就是迭代器的作用。
第一步:两个抽象类,一个抽象 迭代器操作,第一个抽象的 聚合(集合)那种数据结构
public abstract class Iterator { public abstract object First(); public abstract object Next(); public abstract bool IsDone(); public abstract object CurrentItem(); }
然后集合
public abstract class Aggregate { public abstract Iterator CreateIterator(); }
接着拓展 集合操作,和迭代的操作即可,下面定义基本结构
public class AyCollection : Aggregate { private IList<object> items = new List<object>(); public override Iterator CreateIterator() { return new ZhengIterator(this); } } public class ZhengIterator : Iterator { public ZhengIterator(ZhengIterator tor) { } }
完成AyCollection
public class AyCollection : Aggregate { private IList<object> items = new List<object>(); public override Iterator CreateIterator() { return new ZhengIterator(this); } public int Count { get { return items.Count; } } public object this[int index] { get { return items[index]; } set { items.Insert(index, value); } } }
接下来,我们要为客户更简单地来迭代出AyCollection这个集合
public class AyCollection : Aggregate { private IList<object> items = new List<object>(); public override Iterator CreateIterator() { return new ZhengIterator(this); } public int Count { get { return items.Count; } } public object this[int index] { get { return items[index]; } set { items.Insert(index, value); } } } public class ZhengIterator : Iterator { private AyCollection aggregate; private int current = 0; public ZhengIterator(AyCollection tor) { this.aggregate = tor; } public override object First() { return aggregate[0]; } public override object Next() { object ret = null; current++; if (current < aggregate.Count) { ret = aggregate[current]; } return ret; } public override bool IsDone() { return current >= aggregate.Count ? true : false; } public override object CurrentItem() { return aggregate[current]; } }
客户端:
AyCollection cl = new AyCollection(); cl[0] = "a"; cl[1] = "b"; cl[2] = "c"; cl[3] = "d"; StrategyMo.Iterator.Iterator t = new ZhengIterator(cl); while (!t.IsDone()) { Console.WriteLine(t.CurrentItem()); t.Next(); }
接下来,我们实现个逆向输出的
public class NiIterator : Iterator { private AyCollection aggregate; private int current = 0; public NiIterator(AyCollection tor) { this.aggregate = tor; current = aggregate.Count - 1; } public override object First() { return aggregate[0]; } public override object Next() { object ret = null; current--; if (current >=0) { ret = aggregate[current]; } return ret; } public override bool IsDone() { return current <0 ? true : false; } public override object CurrentItem() { return aggregate[current]; } }
AyCollection cl = new AyCollection(); cl[0] = "a"; cl[1] = "b"; cl[2] = "c"; cl[3] = "d"; StrategyMo.Iterator.Iterator t = new ZhengIterator(cl); while (!t.IsDone()) { Console.WriteLine(t.CurrentItem()); t.Next(); } Console.WriteLine("=========逆向输出===="); StrategyMo.Iterator.Iterator t2 = new NiIterator(cl); while (!t2.IsDone()) { Console.WriteLine(t2.CurrentItem()); t2.Next(); }
效果图:
在.NET中, IEnumerator支持对非泛型集合的简单迭代
public interface IEnumerator { bool MoveNext(); //将游标的内部位置向前移动 object Current{get;} //获取当前的项(只读属性) void Reset(); //将游标重置到第一个成员前面 }
IEnumerable公开枚举,非泛型简单迭代
public interface IEnumerable { IEnumerator GetEnumerator(); }
使用的DEMO
Console.WriteLine("=========.NET自带 IEnumerator方式 ay===="); //.NET自带的迭代器。 IList<string> chars = new List<string>() { "a", "b", "c", "d" }; IEnumerator<string> a = chars.GetEnumerator(); while (a.MoveNext()) { Console.WriteLine(a.Current); } Console.WriteLine("=========.NET自带foreach ay===="); foreach (var item in chars) { Console.WriteLine(item); }
讲解:这里List是实现了IEnumerable接口的
所以可以使用a.MoveNext方法,微软封装了foreach方式可以快速对 实现了IEnumerable接口的集合 进行迭代。
在这里,我们用了现成的 List(Aggreate角色)和IEnumerable ( Iterator角色 )
所以你可以实现IEnumerable 接口的集合,来让你的集合可以用foreach方式、
public class UserMi { public string Name { get; set; } } public class AyMi : IEnumerable { List<UserMi> user = new List<UserMi>(); public AyMi() { user.Add(new UserMi { Name = "zhangsan" }); user.Add(new UserMi { Name = "lisi" }); user.Add(new UserMi { Name = "wangwu" }); user.Add(new UserMi { Name = "zhangliu" }); } public IEnumerator GetEnumerator() { return this.user.GetEnumerator(); } }
客户端
AyMi mi = new AyMi(); foreach (var item in mi) { UserMi m=item as UserMi; Console.WriteLine(m.Name); }
效果图: