迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而有不暴露起内部的表示。 【Head First design pattern】
下面来分析一个Demo:
这个就是"聚合对象中的元素"。
ClassA 中使用数组来存储“元素”。
ClassB 中使用List来存储“元素”。
测试代码:
现在我们看看用迭代器模式怎么做:
1.定义接口:
classA对应的迭代器。
3.同时ClassA,ClassB 都继承与IClassA
测试代码:
然后有了迭代器,ClassA ,ClassB 中 GetAll这些方法可以去掉了。
在.net 2.0中完全可以不用这么麻烦,当然如果那么做就不能叫迭代器模式了。实现一个接口全部搞定。
ClassA,ClassB 直接实现接口 System.Collections.IEnumerable
下面来分析一个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; }
}
}
{
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);
//}
}
{
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 源码:{
List<IItem> myitemlist = new List<IItem>();
public List<IItem> GetAllItem()
{
return myitemlist;
}
//public IIterator CreateIterator()
//{
// return new ClassBIterator(myitemlist);
//}
}
enum ItemFlag
{
LOW = -1,
MEDIAL = 0,
HIGH = 1,
}
{
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个类就得用十个循环。{
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");
}
}
现在我们看看用迭代器模式怎么做:
1.定义接口:
interface IIterator
{
bool HasNext();
IItem Next();
}
2. 实现迭代器:{
bool HasNext();
IItem Next();
}
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的迭代器:{
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++];
}
}
Code
interface IClass
{
IIterator CreateIterator();
}
4.取消上面代码的注释。{
IIterator CreateIterator();
}
测试代码:
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);
}
}
}
{
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();
}
{
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;
}
}
{
foreach (IItem s in myitemlist)
{
yield return s;
}
}