设计模式(十六)迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。迭代器模式为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。
.NET 框架中 IEnumerator 支持对 非泛型集合 的简单迭代接口。
1 public interface IEnumerator 2 { 3 object Current 4 { 5 get; // 获取集合中的当前元素 6 } 7 // 将枚举数推进到集合的下一个元素。方法返回值 true 表示迭代器成功前进道集合中的下一个元素,返回值 false 表示已经位于集合的末尾 8 bool MoveNext(); 9 10 // 恢复初始化指向的位置,该位置位于集合中第一个元素之前 11 void Reset(); 12 } 13 14 // 公开枚举数,该枚举数支持在非泛型集合上进行简单迭代 15 public interface IEnumerable 16 { 17 // 返回一个循环访问集合的枚举数 18 IEumerator GetEnumerator(); 19 }
foreach(string item in a) 的内部实现
1 IEnumerator<string> e = a.GetEnumerator(); 2 3 while(e.MoveNext()) 4 { 5 Console.WriteLine("{0}", e.Current); 6 }
基本代码
1 // 迭代器抽象类,用于定义得到开始对象、下一个对象;判断是否到结尾、当前对象等抽象方法,统一接口 2 abstract class Iterator 3 { 4 public abstract object First(); 5 public abstract object Next(); 6 public abstract bool IsDone(); 7 public abstract object CurrentItem(); 8 } 9 10 // 聚集抽象类,创建迭代器 11 abstract class Aggregate 12 { 13 public abstract Iterator CreateIterator(); 14 } 15 16 // 具体聚集类 17 class ConcreteAggregate : Aggregate 18 { 19 // 声明一个 IList 泛型变量,用于存放聚合对象,用 ArrayList 同样可以实现 20 private IList<object> items = new List<object>(); 21 22 public override Iterator CreateIterator() 23 { 24 return new ConcreteIterator(this); 25 } 26 27 // 返回聚集总个数 28 public int Count 29 { 30 get { return items.Count; } 31 } 32 33 // 声明一个索引器 34 public object this[this index] 35 { 36 get { return items[index]; } 37 set { items.Insert(index, value); } 38 } 39 } 40 41 // 具体迭代器类 42 class ConcreteIterator : Iterator 43 { 44 // 定义一个具体聚集对象 45 private ConcreteAggregate aggregate; 46 private int current = 0; 47 48 // 初始化时将具体的聚类对象传入 49 public ConcreteIterator(ConcreteAggregate aggregate) 50 { 51 this.aggregate = aggregate; 52 } 53 54 // 得到聚集的第一个对象 55 public override object First() 56 { 57 return aggregate[0]; 58 } 59 60 // 得到聚集的下一个对象 61 public override object Next() 62 { 63 object ret = null; 64 current++; 65 if(current < aggregate.Count) 66 { 67 ret = aggregate[current]; 68 } 69 return ret; 70 } 71 72 // 判断当前是否遍历到结尾 73 public override bool IsDone() 74 { 75 return current >= aggregate.Count ? true : false; 76 } 77 78 // 返回当前的聚集对象 79 public override object CurrentItem() 80 { 81 return aggregate[current]; 82 } 83 } 84 85 // 实现从后向前反向遍历的具体迭代器类 86 class ConcreteIteratorDesc : Iterator 87 { 88 // 定义一个具体聚集对象 89 private ConcreteAggregate aggregate; 90 private int current = 0; 91 92 // 初始化时将具体的聚类对象传入 93 public ConcreteIteratorDesc(ConcreteAggregate aggregate) 94 { 95 this.aggregate = aggregate; 96 current = aggregate.Count -1; 97 } 98 99 // 得到聚集的第一个对象 100 public override object First() 101 { 102 return aggregate[aggregate.Count -1]; 103 } 104 105 // 得到聚集的下一个对象 106 public override object Next() 107 { 108 object ret = null; 109 current--; 110 if(current >= 0) 111 { 112 ret = aggregate[current]; 113 } 114 return ret; 115 } 116 117 // 判断当前是否遍历到结尾 118 public override bool IsDone() 119 { 120 return current < 0 ? true : false; 121 } 122 123 // 返回当前的聚集对象 124 public override object CurrentItem() 125 { 126 return aggregate[current]; 127 } 128 } 129 130 // 客户端 131 static void Main(string[] args) 132 { 133 // 聚集对象 134 ConcreteAggregate a = new ConcreteAggregate(); 135 a[0] = "1"; 136 a[1] = "2"; 137 a[2] = "3"; 138 139 // 声明迭代器对象 140 Iterator i = new ConcreteIterator(a); 141 //Iterator i = new ConcreteIteratorDesc(a); 142 143 object item = i.First(); 144 while(!i.IsDone()) 145 { 146 Console.WriteLine(); 147 i.Next(); 148 } 149 150 Console.Read(); 151 }
【总结】
迭代器(Iterator)模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。迭代器模式在访问数组、集合、列表等数据时,尤其是数据库操作时,是非常普遍的应用。