在这一章我们将讲述一个如何来迭代一个部门(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,有点紧张的说,表达不到位的地方,还请多多海涵。