.Net行为型设计模式之迭代器模式(Iterator)

作者:springsnow 时间:2024-06-05 09:27:47 

一、动机(Motivate)

在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。
使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种优雅的方式。

二、意图(Intent)

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。                                 ——《设计模式》GoF

三、结构图

.Net行为型设计模式之迭代器模式(Iterator)

四、模式的组成

从迭代器模式的结构图可以看出,它涉及到四个角色,它们分别是:
(1)、抽象迭代器(Iterator):抽象迭代器定义了访问和遍历元素的接口,一般声明如下方法:用于获取第一个元素的first(),用于访问下一个元素的next(),用于判断是否还有下一个元素的hasNext(),用于获取当前元素的currentItem(),在其子类中将实现这些方法。
(2)、具体迭代器(ConcreteIterator):具体迭代器实现了抽象迭代器接口,完成对集合对象的遍历,同时在对聚合进行遍历时跟踪其当前位置。
(3)、抽象聚合类(Aggregate):抽象聚合类用于存储对象,并定义创建相应迭代器对象的接口,声明一个createIterator()方法用于创建一个迭代器对象。
(4)、具体聚合类(ConcreteAggregate):具体聚合类实现了创建相应迭代器的接口,实现了在抽象聚合类中声明的createIterator()方法,并返回一个与该具体聚合相对应的具体迭代器ConcreteIterator实例。

五、迭代器模式的代码实现

迭代器模式在现实生活中也有类似的例子,比如:在部队中,我们可以让某一队伍当中的某人出列,或者让队列里面的每个人依次报名,其实这个过程就是一个遍历的过程。

// 客户端(Client)
static void Main(string[] args)
{
   Iterator iterator;
   ITroopQueue list = new ConcreteTroopQueue();
   iterator = list.GetIterator();

while (iterator.MoveNext())
   {
       string ren = (string)iterator.GetCurrent();
       Console.WriteLine(ren);
       iterator.Next();
   }

Console.Read();
}

// 部队队列的抽象聚合类--该类型相当于抽象聚合类Aggregate
public interface ITroopQueue
{
   Iterator GetIterator();
}

// 迭代器抽象类
public interface Iterator
{
   bool MoveNext();
   Object GetCurrent();
   void Next();
   void Reset();
}

//部队队列具体聚合类--相当于具体聚合类ConcreteAggregate
public sealed class ConcreteTroopQueue : ITroopQueue
{
   private string[] collection;

public ConcreteTroopQueue()
   {
       collection = new string[] { "黄飞鸿", "方世玉", "洪熙官", "严咏春" };
   }

public Iterator GetIterator()
   {
       return new ConcreteIterator(this);
   }

public int Length
   {
       get { return collection.Length; }
   }

public string GetElement(int index)
   {
       return collection[index];
   }
}

// 具体迭代器类
public sealed class ConcreteIterator : Iterator
{
   // 迭代器要集合对象进行遍历操作,自然就需要引用集合对象
   private ConcreteTroopQueue _list;
   private int _index;

public ConcreteIterator(ConcreteTroopQueue list)
   {
       _list = list;
       _index = 0;
   }

public bool MoveNext()
   {
       if (_index < _list.Length)
       {
           return true;
       }
       return false;
   }

public Object GetCurrent()
   {
       return _list.GetElement(_index);
   }

public void Reset()
   {
       _index = 0;
   }

public void Next()
   {
       if (_index < _list.Length)
       {
           _index++;
       }

}
}

六、迭代器模式的实现要点:

1、迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
2、迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
3、迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

迭代器模式的优点:

(1)、迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象。
(2)、迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

迭代器模式的缺点:

迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用foreach语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。

迭代器模式的使用场景:

(1)、访问一个聚合对象的内容而无需暴露它的内部表示。
(2)、支持对聚合对象的多种遍历。
(3)、为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

七、.NET 中迭代器模式的实现

在mscorlib程序集里有这样一个命名空间,该命名空间就是:System.Collections,在该命名空间里面早已有了迭代器模式的实现。对于聚集接口和迭代器接口已经存在了,其中IEnumerator扮演的就是迭代器的角色,它的实现如下:

public interface IEnumerator
{
     object Current
     {
          get;
     }

bool MoveNext();

void Reset();
}

属性Current返回当前集合中的元素,Reset()方法恢复初始化指向的位置,MoveNext()方法返回值true表示迭代器成功前进到集合中的下一个元素,返回值false表示已经位于集合的末尾。能够提供元素遍历的集合对象,在.Net中都实现了IEnumerator接口。
IEnumerable则扮演的就是抽象聚集的角色,只有一个GetEnumerator()方法,如果集合对象需要具备跌代遍历的功能,就必须实现该接口。

public interface IEnumerable
{
   IEumerator GetEnumerator();
}

抽象聚合角色(Aggregate)和抽象迭代器角色(Iterator)分别是IEnumerable接口和IEnumerator接口,具体聚合角色(ConcreteAggregate)有Queue类型, BitArray等类型。

来源:https://www.cnblogs.com/springsnow/p/11358629.html

标签:.Net,行为型,设计,模式,迭代器,Iterator
0
投稿

猜你喜欢

  • python数学建模(SciPy+ Numpy+Pandas)

    2021-02-17 11:05:14
  • python中的mock接口开发示例详解

    2023-03-05 00:53:29
  • 使用matplotlib创建Gif动图的实现

    2021-03-09 11:32:02
  • MySQL中 and or 查询的优先级分析

    2024-01-12 13:53:50
  • python脚本调用iftop 统计业务应用流量的思路详解

    2022-02-07 02:37:12
  • 在pycharm中无法import所安装的库解决方案

    2021-10-20 02:50:11
  • PyQt 线程类 QThread使用详解

    2021-09-18 05:51:37
  • Go到底能不能实现安全的双检锁(推荐)

    2024-04-26 17:36:49
  • python 统计文件中的字符串数目示例

    2022-05-14 11:29:34
  • 不成熟的标准化是我们唯一惧怕的

    2008-08-15 18:55:00
  • Python使用googletrans报错的解决方法

    2021-09-21 01:38:00
  • Python数据结构之链表详解

    2023-07-21 04:16:19
  • python的pstuil模块使用方法总结

    2022-10-09 22:47:16
  • 使用Python的PEAK来适配协议的教程

    2021-08-01 04:12:04
  • ASP UTF-8编码生成静态网页的函数

    2011-03-07 11:24:00
  • Mysql索引创建删除及使用代价

    2024-01-16 15:32:35
  • python PyGame五子棋小游戏

    2023-09-29 13:32:45
  • JS 判断undefined的实现代码

    2024-04-19 09:53:58
  • python使用opencv驱动摄像头的方法

    2023-08-26 17:00:49
  • Golang Gob编码(gob包的使用详解)

    2024-02-22 02:16:46
  • asp之家 网络编程 m.aspxhome.com