在这一章我们将讲述一个如何来迭代一个部门(Department)中的员工(Person)。
我们在用.net 语言输出一个数组时,会使用到for语句:
string[] arr = new string[5];
for(int i=0;i < arr.length; i++)
{
Console.write(arr[i]);
}
这样递增i的值,可以对数组进行依次的遍历。
迭代器模式也是依次遍历并处理多个数字或者变量。
那我们下面来看看迭代器模式的示例。
首先我们定义一个迭代接口Iterator
定义如下:
public interface Iterator
{
bool hasNext();
object next();
}
hasNext()函数的作用在于判断是否有下一个元素,如果有就返回true,如果已经是最后一个元素,就返回flase.
next()函数的用于在于返回聚合当中的某一个元素,细心的同学可能要问,这里的next()是返回当前元素还是下一个元素呢?
答案是 CurrentElementAndAdvanceToNextPostion,就是说其实是返回当前元素,同时移动到下一个位置。
接着,我们定义一个聚合接口Aggregate
定义如下:
public interface Aggregate
{
Iterator iterator();
}
该接口的建立是为了建立一个可对应聚合的Iterator ,可能这句话有点抽象,请大家耐心把后面的程序看完就可以理解这个接口的意义了。
接下来就是我们实体类了,我们迭代一个部门(Department)中的员工(Person)为例子来举例:
员工person类的定义:
public class Person
{
private string name = "";
public Person(string name)
{
this.name = name;
}
public string Name
{
get
{
return name;
}
}
}
这个类很简单,没啥好说的。
部门Department类的定义:
public class Department : Aggregate
{
private Person[] persons;
private int last = 0;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="maxsize"></param>
public Department(int maxsize)
{
this.persons = new Person[maxsize];
}
/// <summary>
/// 返回其中一个员工
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Person getPersonAt(int index)
{
return persons[index];
}
/// <summary>
/// 增加一个员工
/// </summary>
/// <param name="person"></param>
public void AddPerson(Person person)
{
this.persons[last] = person;
last++;
}
/// <summary>
/// 得到部门人员的数量
/// </summary>
/// <returns></returns>
public int getLength()
{
return last;
}
/// <summary>
/// 实现iteraor接口函数
/// </summary>
/// <returns></returns>
public Iterator iterator()
{
return new DepartmentIterator(this);
}
}
说明,这个部门Department类是继承了Aggregate的聚合接口,部门Department作为员工person的员工的容器,需要实现一个迭代的功能,而这个迭代器就是我们最后一个函数的定义:
public Iterator iterator()
{
return new DepartmentIterator(this);
}
这个也是我们为什么会定义一个Aggregate的聚合接口的原因。
ok,下面是我们的具体的部门迭代器DepartmentIterator的定义:
public class DepartmentIterator: Iterator
{
private Department department;
private int index;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="department"></param>
public DepartmentIterator(Department department)
{
this.department = department;
this.index = 0;
}
/// <summary>
/// 是否有下一个员工
/// </summary>
/// <returns></returns>
public bool hasNext()
{
if (index < department.getLength())
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 返回当前的员工,并将位置移动到下一个
/// </summary>
/// <returns></returns>
public Object next()
{
Person person = department.getPersonAt(index);
index++;
return person;
}
}
说明,该部门迭代器继承了迭代器接口,所以会实现hasNext()和next()两种方法。两种方法在迭代器接口中有介绍,这里只是通过部门Department的具体实现。
下面就是我们用于做迭代的测试类了,我们可以在这里看看我们如何利用这些类和接口的定义,实现一个部门里面员工的迭代:
static void Main(string[] args)
{
//定义部门的最大人员个数
Department department = new Department(3);
//往部门里面加入人员
department.AddPerson(new Person("张三"));
department.AddPerson(new Person("李四"));
department.AddPerson(new Person("王五"));
//这句代码很关键,请仔细体会和理解这句代码
Iterator it = department.iterator();
//迭代的实现
while (it.hasNext())
{
Person person = (Person)it.next();
System.Console.WriteLine(person.Name);
}
}
输出的结果是:
张三
李四
王五
说明,Iterator.Iterator it = department.iterator();这句代码很关键,department.iterator();返回的是DepartmentIterator部门迭代器的实例,这个实例又通过多态申明成了Iterator it,it就具有hasNext和next的实现函数,从而实现了迭代。
细心的同学又会提出一个疑问了,Department department = new Department(3);
这里非要事先定义好个数吗?其实并不是这样,你可以在department中用ArrayList来代替person[]。
你也可以根据这个来写一个从最后一个往前迭代的例子。
我们在做项目的时候,常常会对具体类很迷恋,因为他不需要继承,所以耦合度看起来比较低,但实际上,过度的依赖具体类,会使耦合度增加,所以我们要坚持引入抽象类和接口的概念,这样才能增加对OO的认识,增加自己的内功。
对了,说了一些废话,还没有说迭代器的好处呢。
我完全可以用for语句来实现对员工的迭代,那还用迭代器做什么?
ok,答案就在于,iterator可以跟实现进行分离:
请看:
//迭代的实现
while (it.hasNext())
{
Person person = (Person)it.next();
System.Console.WriteLine(person.Name);
}
这里只用到了hasNext和next的方法,并有调用部门类department中的使用方法。
假设我们将person[]改为了ArrayList,用for语句的话,我们将改动这一段for语句的代码。
用迭代器,在department的结构不管怎么改变,我们可以使上面的迭代代码保持不变。
这个也是为什么Iterator it = department.iterator();返回的是Iterator ,而不是具体的实现类DepartmentIterator的原因
各位哥们儿,都看懂了吗?
有什么意见大家可以随便提出来哈,哥们儿我也是第一次写技术类的blog,有点紧张的说,表达不到位的地方,还请多多海涵。