C#设计模式系列:迭代器模式(Iterator)
迭代器模式把对象的职责分离,职责分离可以最大限度减少彼此之间的耦合程度,从而建立一个松耦合的对象。职责分离的要点是对被分离的职责进行封装,并以抽象的方式建立彼此之间的关系。
1、迭代器模式简介
1.1>、定义
迭代器模式提供一种方法可以顺序访问聚合对象中各个元素,但又不暴露该对象的内部表示。
1.2>、使用频率
高
2、迭代器模式结构
2.1>、结构图
2.2>、参与者
迭代器模式参与者:
◊ Iterator:迭代器定义访问和遍历元素的接口
◊ ConcreteIterator
° 具体迭代器实现迭代器接口
° 对该聚合遍历时跟踪当前位置
◊ Aggregate:聚合定义创建Iterator对象的接口
◊ ConcreteAggregate:具体聚合,实现相应迭代器的接口,返回具体迭代器的一个适当的实例。
在迭代器模式中,ConcreteAggregate通过Aggregate定义的接口得到Iterator,并且这是一个ConcreteIterator,该ConcreteIterator具体实现了对ConcreteAggregate的访问与遍历的方法。通过ConcreteIterator可以访问并使用集合中的元素。
3、迭代器模式结构实现
Iterator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Structural { public abstract class Iterator { public abstract object First(); public abstract object Next(); public abstract bool IsDone(); public abstract object CurrentItem(); } }
Aggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Structural { public abstract class Aggregate { public abstract Iterator CreateIterator(); } }
ConcreteAggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; namespace DesignPatterns.IteratorPattern.Structural { public class ConcreteAggregate : Aggregate { private ArrayList _items = new ArrayList(); 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); } } } }
ConcreteIterator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Structural { public 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; if (_current < _aggregate.Count - 1) { ret = _aggregate[++_current]; } return ret; } public override object CurrentItem() { return _aggregate[_current]; } public override bool IsDone() { return _current >= _aggregate.Count; } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.IteratorPattern.Structural; namespace DesignPatterns.IteratorPattern { class Program { static void Main(string[] args) { ConcreteAggregate a = new ConcreteAggregate(); a[0] = "Item A"; a[1] = "Item B"; a[2] = "Item C"; a[3] = "Item D"; ConcreteIterator i = new ConcreteIterator(a); Console.WriteLine("Iterating over collection:"); object item = i.First(); while (item != null) { Console.WriteLine(item); item = i.Next(); } } } }
运行输出:
Iterating over collection:
Item A
Item B
Item C
Item D
请按任意键继续. . .
4、迭代器模式实践应用
在迭代器模式的设计中,有两种具体的实现方式,分别为外禀迭代器和内禀迭代器。白箱聚集与外禀迭代器:白箱聚集向外界提供访问自己内部元素的接口,从而使得外禀迭代器可以通过聚集提供的方法实现迭代功能。黑箱聚集与内禀迭代器:黑箱聚集不向外界提供遍历自己内部元素的接口,因此聚集的成员只能被聚集内部的方法访问。由于内禀迭代器恰好也是聚集的成员,因此可以访问聚集元素。
4.1、外禀迭代器
外禀迭代器的迭代过程使用了集合中的元素,通过集合向外界提供了访问自身内部元素的机会。
Iterator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator { /// <summary> /// 定义一个迭代器接口 /// </summary> public interface Iterator { /// <summary> /// 迭代器定位到聚合的第一个元素 /// </summary> void First(); /// <summary> /// 遍历下一个 /// </summary> void Next(); /// <summary> /// 判断是否完成遍历 /// </summary> /// <returns></returns> bool IsDone(); /// <summary> /// 获得当前遍历的项 /// </summary> /// <returns></returns> object CurrentItem(); } }
ConcreteIterator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator { /// <summary> /// 定义具体的迭代器类 /// </summary> public class ConcreteIterator : Iterator { private ConcreteAggregate aggregate; private int index = 0; private int size = 0; /// <summary> /// 根据不同的聚合类进行初始化 /// </summary> /// <param name="aggregate"></param> public ConcreteIterator(ConcreteAggregate aggregate) { this.aggregate = aggregate; size = aggregate.Size(); index = 0; } public void First() { index = 0; } public void Next() { if (index < size) { index++; } } /// <summary> /// 判断是否遍历完毕 /// </summary> /// <returns></returns> public bool IsDone() { return index >= size; } /// <summary> /// 获取当前遍历的元素 /// </summary> /// <returns></returns> public object CurrentItem() { return aggregate.GetElement(index); } } }
Aggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator { /// <summary> /// 定义一个抽象的聚合类 /// </summary> public abstract class Aggregate { /// <summary> /// 只有一个功能,创建迭代器 /// </summary> /// <returns></returns> public virtual Iterator CreateIterator() { return null; } } }
ConcreteAggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator { /// <summary> /// 定义一个具体的聚合类 /// </summary> public class ConcreteAggregate : Aggregate { // 存储元素的集合 private object[] objs = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; /// <summary> /// 获得元素个数 /// </summary> /// <returns></returns> public int Size() { return objs.Length; } /// <summary> /// 获取指定序号的元素 /// </summary> /// <param name="index">指定的序号</param> /// <returns></returns> public object GetElement(int index) { if (index < 0 || index > objs.Length) { return null; } return objs[index]; } /// <summary> /// 创建该聚合类的迭代器 /// </summary> /// <returns></returns> public override Iterator CreateIterator() { return new ConcreteIterator(this); } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.ExtrinsicIterator { public class Client { private Iterator _iterator; private Aggregate _aggregate = new ConcreteAggregate(); public void Operation() { // 获得迭代器 _iterator = _aggregate.CreateIterator(); while (!_iterator.IsDone()) { Console.WriteLine(_iterator.CurrentItem()); _iterator.Next(); } } static void Main(string[] args) { Client client = new Client(); client.Operation(); } } }
运行输出:
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
请按任意键继续. . .
4.2、内禀迭代器
内禀迭代器实现的关键是在集合的内部定义一个私有的具体迭代子类,由它来负责迭代器的所有功能。因为它是集合的私有类,所以它的对象可以遍历集合的内部元素,实现迭代器定义的所有接口,而集合本身并未向外界提供访问自己内部元素的接口。
Iterator.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator { /// <summary> /// 定义一个迭代器接口 /// </summary> public interface Iterator { /// <summary> /// 迭代器定位到聚合的第一个元素 /// </summary> void First(); /// <summary> /// 遍历下一个 /// </summary> void Next(); /// <summary> /// 判断是否完成遍历 /// </summary> /// <returns></returns> bool IsDone(); /// <summary> /// 获得当前遍历的项 /// </summary> /// <returns></returns> object CurrentItem(); } }
Aggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator { /// <summary> /// 定义一个抽象的聚合类 /// </summary> public abstract class Aggregate { /// <summary> /// 只有一个功能,创建迭代器 /// </summary> /// <returns></returns> public virtual Iterator CreateIterator() { return null; } } }
ConcreteAggregate.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator { /// <summary> /// 定义一个具体的聚合类 /// </summary> public class ConcreteAggregate : Aggregate { // 存储元素的集合 private static object[] objs = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; /// <summary> /// 定义具体的迭代器类 /// </summary> private class ConcreteIterator : Iterator { private int _index = 0; public void First() { _index = 0; } public void Next() { if (_index < objs.Length) { _index++; } } public bool IsDone() { return _index == objs.Length; } public object CurrentItem() { return objs[_index]; } } /// <summary> /// 获得元素个数 /// </summary> /// <returns></returns> public int Size() { return objs.Length; } /// <summary> /// 获取指定序号的元素 /// </summary> /// <param name="index">指定的序号</param> /// <returns></returns> public object GetElement(int index) { if (index < 0 || index > objs.Length) { return null; } return objs[index]; } /// <summary> /// 创建该聚合类的迭代器 /// </summary> /// <returns></returns> public override Iterator CreateIterator() { return new ConcreteIterator(); } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.IteratorPattern.Practical.IntrinsicIterator { public class Client { private Iterator _iterator; private Aggregate _aggregate = new ConcreteAggregate(); public void Operation() { // 获得迭代器 _iterator = _aggregate.CreateIterator(); while (!_iterator.IsDone()) { Console.WriteLine(_iterator.CurrentItem()); _iterator.Next(); } } static void Main(string[] args) { Client client = new Client(); client.Operation(); } } }
5、迭代器模式应用分析
迭代器模式适用情形:
1>、访问一个具体对象的内容而不暴露它的内部表示;
2>、支持对聚合对象的多种遍历;
3>、为遍历不同的聚合结构提供一个统一的接口(即支持多态迭代)。
迭代器模式特点:
1>、简化聚集的行为,迭代器具备了遍历的接口,这样聚集的接口就不必具备遍历接口;
2>、每一个聚集对象都可以有一个或者更多的迭代器对象,每一个迭代器的迭代状态可以彼此独立(外禀迭代器);
3>、遍历算法被封装到迭代器对象中,迭代算法可以独立于聚集对象变化。Client不必知道聚集对象的类型,通过迭代器可以就读取和遍历聚集对象。这样的好处是聚集本身内部数据发生变化而不影响Client的程序。