迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而有不暴露起内部的表示。 【Head First design pattern】

下面来分析一个Demo:
这个就是"聚合对象中的元素"。
  class ItemFir:IItem
    
{
        
string name;
        ItemFlag flag;

        
public ItemFlag Flag
        
{
            
get return flag; }
            
set { flag = value; }
        }

        
        
public ItemFir(string name, string des,ItemFlag itemflag)
        
{
            
this.des = des;
            
this.name = name;
            
this.flag = itemflag;
        }

        
public string Name
        
{
            
get return name; }
            
set { name = value; }
        }


        
string des;

        
public string Des
        
{
            
get return des; }
            
set { des = value; }
        }

    }

ClassA 中使用数组来存储“元素”。

  class ClassA
    
{
        IItem[] myitemlist 
= new ItemFir[10];
        

        
public IItem[] GetAll()
        
{
            
return myitemlist;
        }

        
//public IIterator CreateIterator()
        
//{
        
//    return new ClassAIterator(myitemlist);
        
//}
    }

ClassB 中使用List来存储“元素”。
  class ClassB
    
{
        List
<IItem> myitemlist = new List<IItem>();
        

        
public List<IItem> GetAllItem()
        
{
            
return myitemlist;
        }

        
//public IIterator CreateIterator()
        
//{
        
//    return new ClassBIterator(myitemlist);
        
//}
    }
ItemFlag 源码:
enum ItemFlag
    
{
        LOW 
= -1,
        MEDIAL 
= 0,
        HIGH 
= 1,
    }

测试代码:
  static void Main(string[] args)
        
{
            ClassA classA 
= new ClassA();
            IItem[] itemlistA 
= classA.GetAll();
            Console.Write(
"ClassA\n");


            
for (int i = 0; i < itemlistA.Length; i++)
            
{
                
if (itemlistA[i].Flag == ItemFlag.LOW)
                    Console.Write(itemlistA[i].Name 
+ "  " + itemlistA[i].Flag + "\n");
            }

            Console.Write(
"ClassB\n");
            ClassB classB 
= new ClassB();
            List
<IItem> itemlistB = classB.GetAllItem();

            
for (int j = 0; j < itemlistB.Count; j++)
            
{
                
if (itemlistB[j].Flag == ItemFlag.LOW)
                    Console.Write(itemlistB[j].Name 
+ " " + itemlistB[j].Flag + "\n");
            }

}
我们希望把 ClassA 中和ClassB 中所有ItemFalg 值为LOW的元素选择出来。其实对于客户来说没必要知道你用数组还是list来保存的。客户需要用不同的方式来访问聚合,也显得不够优雅。( itemlistB.Count ,itemlistA.Length)还有像上面如果有10个类就得用十个循环。
现在我们看看用迭代器模式怎么做:

1.定义接口:
 interface IIterator
    
{
        
bool HasNext();
        IItem Next();
        
    }
2. 实现迭代器:
classA对应的迭代器。
  class ClassAIterator : IIterator
    
{
        
int posion;
        IItem[] item;
        
public ClassAIterator(IItem[] item)
        
{
            
this.item = item;
        }


        
public bool HasNext()
        
{
            
return posion <= item.Length - 1;
        }


        
public IItem Next()
        
{
            
return item[posion++];
        }


    }
ClassB的迭代器:

Code
3.同时ClassA,ClassB 都继承与IClassA
 interface IClass
    
{
         IIterator CreateIterator();
    }
4.取消上面代码的注释。


测试代码:
   class Context
    
{
        System.Collections.ArrayList arr 
= null;

        
public Context(ArrayList arr)
        
{
            
this.arr = arr;
        }


        
//因为可以用相同的方式遍历,所以不管有多少 IClass的实例 下面两个方法都不用更改
        public void Print()
        
{
            IEnumerator ien 
= arr.GetEnumerator();
            
while (ien.MoveNext())
            
{
                IClass iclass 
= (IClass)ien.Current;
                Print(iclass.CreateIterator());
            }

        }

        
void Print(IIterator iit)
        
{
           
while(iit.HasNext())
            
{
                IItem item 
= iit.Next();
                Console.WriteLine(item.Name 
+ " " +item.Flag);
            }

        }

    }


  static void Main(string[] args)
        
{

            ArrayList arr 
= new ArrayList();
            arr.Add(
new ClassA());
            arr.Add(
new ClassB());
            Context ctx 
= new Context(arr);
            ctx.Print();
            Console.ReadLine();
        }

然后有了迭代器,ClassA ,ClassB 中 GetAll这些方法可以去掉了。
在.net 2.0中完全可以不用这么麻烦,当然如果那么做就不能叫迭代器模式了。实现一个接口全部搞定。
ClassA,ClassB 直接实现接口 System.Collections.IEnumerable

 public IEnumerator GetEnumerator()
        
{
            
foreach (IItem s in myitemlist)
            
{
                
yield return s;
            }
 
        }