設計模式系列
目的:提供方法走訪集合內的物件,走訪過程不需知道集合內部結構。
而在C#中,使用foreach語法本身就可以算是在使用Iterator Pattern了。
使用時機:
- 需要訪問一個聚合物件內容,而無須暴露內部。
- 需要支援聚合物件的多種反覆。
- 需要不同的聚合結構提供一個統一介面。
class Program
{
static void Main(string[] args)
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "大鳥";
a[1] = "小菜";
a[2] = "行李";
a[3] = "老外";
a[4] = "公交內部員工";
a[5] = "小偷";
Iterator i = new ConcreteIterator(a);
while (!i.IsDone())
{
Console.WriteLine($"{i.CurrentItem()}請買車票!");
i.Next();
}
}
}
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
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);}
}
}
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;
}
public override object CurrentItem()
{
return aggregate[current];
}
public override bool IsDone()
{
return current >= aggregate.Count ? true : false;
}
}
class ConcreteIteratorDesc:Iterator
{
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIteratorDesc(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
current = aggregate.Count - 1;
}
public override object First()
{
return aggregate[aggregate.Count - 1];
}
public override object Next()
{
object ret = null;
current--;
if (current >= 0) {
ret = aggregate[current];
}
return ret;
}
public override object CurrentItem()
{
return aggregate[current];
}
public override bool IsDone()
{
return current < 0 ? true : false;
}
}
缺點:遍歷的同時更改迭代器所在的集合結構會導致出現異常,只能使用foreach對集合進行遍歷,不能在遍歷的同時更改集合中的元素。
元哥的筆記