设计模式Iterator Pattern迭代者模式

所谓迭代者模式就是:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。[GOF 《设计模式》] 
  在软件的构建过程中,集合对象(也就是聚集:是一组数据集或者对象集,它可以通过循环来访问 )内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也 为“同一种算法在多种集合对象上进行操作”提供了可能。使用面向对象技术将这种遍历机制抽象为“迭代器对象”为“应对变化中的集合对象”提供了一种比较好 的方式。
  我们在平时的开发中经常直接或间接地使用到此模式,我们使用foreach语句来循环就是在间接的使用C# Iterator迭代器模式。
  迭代器就像指针一样可以向前向后移动,在.NET中迭代器只能向后移动。
  此模式的UML图如下:

                        

  由图可知,它有以下角色

     1、Aggregate 接口: 抽象的聚集,通常只留有一个方法让子类去实现,这个方法的作用是获得一个枚举器对象,通常可以起名字为 GetIterator( ),CreateIterator( ) 等等,或者干脆叫做 Iterator( ) 也行。在 C# 中,这个方法的名字叫做 GetEnumerator( ) ,这个我们到后面再讲。当然,在获得枚举器的同时,也要把自己 this(一组数据集)当作参数传给枚举器,想想也是,如果没有数据集,枚举器去枚举什么呢?
     2、ConcreteAggregate 类: 具体的聚集,它的实例保存了一组数据集,同时它实现了 Aggregate 接口中唯一的那个方法,通常情况下他也会扩展出一些其他方法便于访问聚集中的数据,常见的有:访问某个位置数据的方法,可以叫做 GetElement(int index) 或者 GetItem(int index) 等等;获得聚集大小的方法,可以起名字为 GetLength( ) 或者 GetSize( ) 等等,全看自己喜好。我们这里叫Count。
     3、Iterator 接口: 抽象的枚举器,通常情况下会有三个方法留给子类去实现,他们分别是:Next( ) ,用来把指针移动到聚集中的下一个数据;HasNext( ) ,用来判断是否还有下一个数据;CurrentItem( ),返回当前指针所指位置的数据。也可以把 Next( ) 和 CurrentItem( ) 组成一个方法,在移动指针的同时返回一个数据。也可以有其他的实现方式,或者简单,或者复杂,也是全看个人需求。
     4、ConcreteIterator 类:具体的枚举器,它实现了上述的三个方法,通过不同的实现方式,我们可以获得不同的枚举方式,如顺序枚举、倒序枚举等等。当然,这个类的构造方法中会接受一个具体聚集参数,想想也是,如果没有这个数据集,他去枚举什么呢?这个参数就是他要去枚举的对象。
     5、被聚集的类,这个可以是任何类,它的许多个对象被存到聚集对象中才能形成一个真正的聚集。
   下面,我们用两段代码来示例此模式。
   程序如下图:   
                        
  一、迭代者模式运基本思想示例
   1、Aggregate 接口:Aggregate.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
#region 定义Aggregate抽象类
    
//实现迭代接口,返回迭代器  
    abstract  class Aggregate
    {
        
////在这里进行解藕,将集合对象转换为迭代器  
        public abstract Iterator CreateIterator();
    }
    
#endregion
}

   2、ConcreteAggregate 类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyIterator
{
    
//定义ConcreteAggregate类,它继承自Aggregate
    class ConcreteAggregate:Aggregate 
    {
        
private ArrayList _items = new ArrayList();
        
#region 实现基类Aggregate定义的操作CreateIterator
        
public override Iterator CreateIterator()
        {
            
//因为在ConcreteIterator构造函数中需要传入ConcreteAggregate类的实例
            
//所以在此处实现CreateIterator功能时ConcreteAggregate类实例作为参数传入
            
//从而在ConcreteAggregate与CreateIterator之间建立了联系
            return new ConcreteIterator(this);
        }
        
#endregion

        
#region 得到Item的数目
        
public int Count
        {
            
get { return _items.Count; }
        }
        
#endregion

        
#region 获取指定位置的元素
        
public object this[int index]
        {
            
get { return _items[index]; }
            
set { _items.Insert(index, value); }
        }
        
#endregion
    }
}

   3、Iterator 接口


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
#region 定义Interator接口
    
//此处定义了Interator子类需要实现的遍历操作
    public  abstract class Iterator
    {
        
public abstract object First();
        
public abstract object Next();
        
public abstract bool IsDone();
        
public abstract object CurrentItem();
    }
    
#endregion
}

   4、ConcreteIterator 类:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
#region 定义ConcreteInterator类
         
//此类继承自Interator类,实现了迭代器接口  
        
//First();  Next(); IsDone();CurrentItem();
    class ConcreteIterator:Iterator 
    {
        
private ConcreteAggregate _aggregate;
        
private int _current = 0;

        
#region 构造函数
        
//构造时引入集合实例aggregate,从而将集合类型转换成内部成员  
        
//我们通过ConcreteIterator方法,将集合对象转换为了可迭代对象,这实际上是在对集合对象进行抽象,将他转换为迭代器
        public ConcreteIterator(ConcreteAggregate aggregate)
        {
            
this._aggregate = aggregate;
        }
        
#endregion

        
#region 得到第一个元素
        
public override object First()
        {
            
return _aggregate[0];
        }
        
#endregion

        
#region 得到当前元素的下一个元素
        
public override object Next()
        {
            
object retObject = null;
            
if( _current<_aggregate.Count-1 )
            {
                
//如果当前项后面还有元素则取得下一个元素并返回
                retObject = _aggregate[++_current];
            }
            
return retObject;
        }

        
#endregion

        
#region 取得当前项元素
        
public override object CurrentItem()
        {
            
return _aggregate[_current];
        }

        
#endregion

        
#region 是否遍历完所有元素
        
public override bool IsDone()
        {
            
return _current >= _aggregate.Count;
        }

        
#endregion
    }
    
#endregion
}

   5、被聚集的类,此处我们用字符串来实现
  6、客户端应用


            #region 运作思想示例
            
//定义一个集合对象并初始化
            ConcreteAggregate ca = new ConcreteAggregate();
            
for (int i = 0; i < 8; i++)
            {
                ca[i] 
= "Item " + (i + 1).ToString();
            }

            
//创建一个迭代器,并传入上面创建的集合对象
            ConcreteIterator ci = new ConcreteIterator(ca);
            Console.WriteLine(
"--------------遍历集合对象-----------");

            
object item = ci.First();
            
while (item != null)
            {
                Console.WriteLine(item);
                item 
= ci.Next();
            }

            Console.ReadKey();
            
#endregion

 

  二、以士兵作为被聚集的类来示例实现
   1、Aggregate 接口:IAbstractCollection接口


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyIterator
{
    
#region IAbstractCollection接口
    
interface  IAbstractCollection
    {
        
        SoldierIterator CreateIterator();
    }
    
#endregion
}

   2、ConcreteAggregate 类: SoldierCollection类


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyIterator
{
    
class SoldierCollection:IAbstractCollection 
    {
       
        
private ArrayList _item = new ArrayList();

        
//返回迭代器  
        public SoldierIterator CreateIterator()
        {
            
return new SoldierIterator(this);
        }

        
#region 获取当前集合对象的元素数目
        
public int Count
        {
            
get { return _item.Count;}
        }
        
#endregion

        
#region 获取指定位置的元素
        
public object this[int index]
        {
            
get { return _item[index]; }
            
set { _item.Add(value); }
        }

        
#endregion
    }
}

   3、Iterator 接口: IAbstractIterator接口


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
#region  
    
interface IAbstractIterator
    {
        
//要求实现First,Next,IsDone与CurrentItem功能
        Soldier First();
        Soldier Next();
        
bool IsDone{get;}
        Soldier CurrentItem {
get; }
    }
    
#endregion
}

   4、ConcreteIterator 类:SoldierIterator类


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
class SoldierIterator:IAbstractIterator 
    {
        
private SoldierCollection _collection;
        
private int _current = 0;
        
private int _step = 1;
        
#region 构造函数
        
public SoldierIterator(SoldierCollection collection)
        {
            
this._collection = collection;
        }
        
#endregion

        
#region 得到队列中的第一名士兵
        
public Soldier First()
        {
            _current 
= 0;
            
return _collection[_current] as Soldier;
        }

        
#endregion

        
#region 得到下一名士兵
        
public Soldier Next()
        {
            _current 
+= _step;
            
if (!IsDone)
            {
                
return _collection[_current] as Soldier;
            }
            
else
            {
                
return null;
            }

        }
        
#endregion

        
#region 获取或设置前进步伐
        
public int Step
        {
            
get { return _step; }
            
set { _step = value; }
        }
        
#endregion

        
#region 获取当前士兵
        
public Soldier CurrentItem
        {
            
get { return _collection[_current] as Soldier; }
        }
        
#endregion

        
#region 判断是否遍历完成
        
public bool IsDone
        {
            
get { return _current >= _collection.Count; }
        }
        
#endregion



    }
}

   5、被聚集的类:Soldier


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyIterator
{
    
class Soldier
    {
        
#region Name属性
        
private string _name;
        
public string Name
        {
            
get { return _name; }
        }
        
#endregion

        
#region 构造函数
        
public Soldier(string name)
        {
            
this._name = name;
        }
        
#endregion


    }
}

  6、客户端应用 


            #region 我的团长我的团
            SoldierCollection collection 
= new SoldierCollection();
            collection[
0= new Soldier("孟烦了");
            collection[
1= new Soldier("不辣");
            collection[
2= new Soldier("迷龙");
            collection[
3= new Soldier("豆饼");
            collection[
4= new Soldier("要麻");
            collection[
5= new Soldier("蛇屁股");
            collection[
6= new Soldier("康丫");
            collection[
7= new Soldier("郝兽医");
            collection[
8= new Soldier("阿译");

            SoldierIterator si 
= new SoldierIterator(collection);

            
//设置指针前移距离
            si.Step = 1;
            
//按指定步距遍历一次
            Console.WriteLine("--------我的团长我的团----------");

            
//Soldier sd = si.First();
            
//while(sd!=null)
            
//{
            
//    Console.WriteLine(sd.Name);
            
//    sd=si.Next();
            
//}

            
for (Soldier sd = si.First(); !si.IsDone; sd = si.Next())
            {
                Console.WriteLine(sd.Name);
            }
            Console.ReadKey();

            
#endregion

  运行效果如下:
                          


 

前往:设计模式学习笔记清单
原文地址:https://www.cnblogs.com/smallfa/p/1602902.html