迭代器模式
文章目录
- 迭代器模式
- 模式分类
- 模式产生的原因
- 模式的灵感来源
- 模式类图
- 代码实现
- 迭代器模式总结
- 迭代器模式的优点:
- 迭代器模式的缺点:
本篇博客将介绍迭代器模式,迭代器模式将一个聚合对象保存数据的职责,和它遍历数据的职责分离,在引入迭代器后,聚合对象只负责保存数据,而遍历数据交给迭代器来完成。迭代器模式的介绍将参考.NET中的迭代器来进行说明。
模式分类
行为型设计模式。
模式产生的原因
在软件开发中,为了可以更加方便的操作聚合对象,同时可以很灵活的为聚合对象增加不同的遍历方法,我们需要一个解决方案可以让我们访问一个聚合对象但又不需要暴露它的内部结构。迭代器模式为我们解决了这个问题。它提供一种可以顺序访问一个聚合对象各个元素的方法且不会暴露该对象的内部表示。
模式的灵感来源
在现实生活中,人们有两种方法来操作电视机实现开机,关机,换台等操作。一种方法是使用电视机本身提供的操作面板上的按钮来说直接实现,另一种则是通过遥控器来间接控制电视机。遥控器的出现为电视机的操作带带来了极大的方便,用户并不需要知道电视机中是怎么存储频道的就可以实现换台。
模式类图
由图可知,迭代器模式由4个对象构成:
Aggregate(抽象聚合对象):
抽象聚合对象是所有的聚合对象的父类,它提供了一个获得迭代器的方法,在.NET中这个方法被封装在了另一个接口中,其实为了更加彻底的解耦,我们也可以采用.NET的方法,将GetIterator单独封装在一个接口中。
ConcreteAggregate(具体聚合对象):
具体的聚合对象,负责存储数据和获得迭代器,以方便遍历。
AbstractIterator(抽象迭代器):
抽象迭代器中有如何遍历聚合对象的基础方法,在具体迭代器中我们需要实现这些方法。
ConcreteIterator(具体迭代器):
具体迭代器负责实现抽象迭代器中的方法,并且要实现自己独有的遍历方法,一般我们可以在具体迭代器中书写当前迭代器的迭代逻辑。
代码实现
在代码实现里我使用了代理模式来延迟创建具体的迭代器,这样更加方便了实际使用的用户,但是加大了代码的书写逻辑。
抽象迭代器类:
using System.Collections.Generic;namespace Iterator.Iterator.Question3
{public abstract class MyIterator{protected List<int> MyList;protected int Index;public MyIterator(string name, List<int> list){MyList = list;}public abstract bool MoveNext();public abstract object Current();public abstract void Reset();}
}
获得迭代器接口:
namespace Iterator.Iterator.Question3
{public interface INewGetIterator{MyIterator GetIterator();}
}
迭代器代理类:
using System.Collections.Generic;
using System.Runtime.InteropServices;namespace Iterator.Iterator.Question3
{public class MCollectionAgent : MyIterator{private MyIterator _iterator;public MCollectionAgent(string name, List<int> list) : base(name, list){switch (name){case "AsOrder":_iterator = new AsOrder(name, list);break;case "DesOrder":_iterator = new DesOrder(name, list);break;}}public override bool MoveNext(){return _iterator.MoveNext();}public override object Current(){return _iterator.Current();}public override void Reset(){_iterator.Reset();}}
}
抽象聚合对象类:
using System.Collections.Generic;
using Iterator.Iterator.Example;namespace Iterator.Iterator.Question3
{public abstract class CollectionObject : INewGetIterator{protected List<int> MyList;public abstract MyIterator GetIterator();}
}
具体聚合对象A:
using System.Collections.Generic;namespace Iterator.Iterator.Question3
{public class CollectionA : CollectionObject{private string _name;public CollectionA(string name){_name = name;MyList = new List<int>(){1,2,3,4,5,6,7,8,9};}public override MyIterator GetIterator(){return new MCollectionAgent(_name, MyList);}}
}
升序遍历迭代器:
using System.Collections.Generic;namespace Iterator.Iterator.Question3
{public class AsOrder : MyIterator{public override bool MoveNext(){Index++;if (Index < MyList.Count){return true;}return false;}public override object Current(){return MyList[Index];}public override void Reset(){Index = -1;}public AsOrder(string name, List<int> list) : base(name,list){Index = -1;}}
}
降序遍历迭代器:
using System.Collections.Generic;namespace Iterator.Iterator.Question3
{public class DesOrder : MyIterator{public DesOrder(string name, List<int> list) : base(name, list){Index = MyList.Count;}public override bool MoveNext(){Index--;if (Index >= 0){return true;}return false;}public override object Current(){return MyList[Index];}public override void Reset(){Index = MyList.Count; }}
}
Program类:
using System;
using Iterator.Iterator.Question3;namespace Iterator
{internal class Program{public static void Main(string[] args){//降序遍历CollectionObject collectionObject = new CollectionA("DesOrder");MyIterator iterator = collectionObject.GetIterator();while (iterator.MoveNext()){Console.WriteLine(iterator.Current());}}}
}
迭代器模式总结
迭代器模式的优点:
- 迭代器模式支持以不同的方式遍历一个聚合对象,在同一个聚合对象中可以定义多种遍历方法。
- 迭代器简化了聚合对象,现在的聚合对象将不需要再考虑自己提供数据遍历的方法。
迭代器模式的缺点:
- 迭代器模式的使用会增加系统的复杂性。
- 迭代器模式的设计难度比较大,需要充分考虑系统将来的扩展。