17.Iterator迭代器(行为型模式)

本文详细介绍了迭代器模式,这是一种设计模式,用于在不暴露内部结构的情况下遍历聚合对象。通过将遍历行为分离到迭代器类,实现了数据结构的隐藏并提供了统一的遍历接口。生活中的例子如公交车售票员检票,代码示例展示了如何在.NET环境中实现迭代器模式。适用性包括访问聚合内容、支持多种遍历和统一接口。总结强调了迭代器模式的抽象性和多态性,以及在遍历过程中对集合结构的保护。
摘要由CSDN通过智能技术生成

一:动机(Motivation)

<1>在面向对象的软件设计中,我们经常会遇到一类集合对象,这类集合对象的内部结构可能有着各种各样的实现,但是归结起来,无非有两点是需要我们去关心的:一是集合内部的数据存储结构,二是遍历集合内部的数据。面向对象设计原则中有一条是类的单一职责原则,所以我们要尽可能的去分解这些职责,用不同的类去承担不同的职责。

<2>Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。

二:意图(Intent)

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
——《设计模式》GoF

三:结构(Structure)

在这里插入图片描述

四:结构详解

在这里插入图片描述

五:生活中的例子

<1>在公交车上,售票员不管上来的是什么人,总会要求每个人都来买票。
<2>不管乘客是什么,售票员的做法都是相同的:
从第一个开始
当前是谁
下一个
是否结束

六:实现

namespace Test
{
    /// <summary>
    /// 迭代器,用来执行迭代操作
    /// </summary>
    public abstract class Iterator
    {
        public abstract object First();  //第一个
        public abstract object CurrentItem();  //当前这一个
        public abstract object Next();  //下一个
        public abstract bool IsDone();  //结束了没有?
    }

    /// <summary>
    /// 聚合类,代表一个可迭代的集合
    /// </summary>
    public abstract class Aggregate
    {
        public abstract Iterator CreateIterator();  //返回一个迭代器
    }

    /// <summary>
    /// ConcreteAggregate  具体的聚合类
    /// </summary>
    public class 车上的乘客 : Aggregate
    {
        private System.Collections.ArrayList al = new System.Collections.ArrayList();

        public override Iterator CreateIterator()
        {
            return new ConcreteIterator(this);
        }

        public void 上车(string 乘客姓名)
        {
            this.al.Add(乘客姓名);
        }

        public string this[int index]
        {
            get
            {
                return this.al[index].ToString();
            }
        }

        public int 数量
        {
            get
            {
                return this.al.Count;
            }
        }
    }

    /// <summary>
    /// ConcreteIterator  具体的迭代器
    /// </summary>
    public class ConcreteIterator : Iterator
    {
        private 车上的乘客 _乘客们 = null;

        private int 当前第几个 = 0;

        public ConcreteIterator(车上的乘客 乘客)
        {
            this._乘客们 = 乘客;
        }

        public override object First()
        {
            if (this._乘客们.数量 > 0)
            {
                this.当前第几个 = 0;
                return this._乘客们[0];
            }
            else
            {
                return null;
            }
        }

        public override object CurrentItem()
        {
            return this._乘客们[当前第几个];
        }

        public override object Next()
        {
            this.当前第几个++;
            if (this.当前第几个 < this._乘客们.数量)
            {
                return this._乘客们[当前第几个];
            }
            else
            {
                return null;
            }
        }

        public override bool IsDone()
        {
            return this.当前第几个 >= this._乘客们.数量;
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            车上的乘客 隧道六线 = new 车上的乘客();
            隧道六线.上车("张三");
            隧道六线.上车("李四");
            隧道六线.上车("王五");
            隧道六线.上车("赵六");

            Iterator iterator = 隧道六线.CreateIterator();

            while (!iterator.IsDone())
            {
                Console.WriteLine("{0},请你买票,谢谢!", iterator.CurrentItem());
                iterator.Next();
            }
            Console.ReadLine();
        }
    }
}

在这里插入图片描述

七:适用性

<1>访问一个聚合对象的内容而无需暴露它的内部表示。
<2>支持对聚合对象的多种遍历。
<3>为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代)。

namespace Test
{
    /// <summary>
    /// 聚合对象(集合)
    /// </summary>
    public abstract class Aggregate
    {
        public abstract Iterator CreateIterator();
    }

    /// <summary>
    /// 迭代器:能遍历一个集合的遍历行为
    /// </summary>
    public abstract class Iterator
    {
        public abstract object First();
        public abstract void Next();
        public abstract object Current();
        public abstract bool IsDone
        {
            get;
        }
    }

    /// <summary>
    /// 一年级
    /// </summary>
    public class FirstGrade : Aggregate
    {
        public override Iterator CreateIterator()
        {
            //return new FirstGradeAsceIterator(this);
            return new FirstGradeDeAsceIterator(this);
        }

        private List<Student> students = new List<Student>();
        public void AddStudent(Student student)
        {
            this.students.Add(student);
        }

        public int StudentsCount
        {
            get { return this.students.Count; }
        }

        public Student this[int index]
        {
            get { return this.students[index]; }
        }
    }

    public class Student
    {
        public Student(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }
        public override string ToString()
        {
            return this.Name;
        }
    }

    /// <summary>
    /// 按照升序迭代
    /// </summary>
    public class FirstGradeAsceIterator : Iterator
    {
        /// <summary>
        /// 关联到需要迭代的一年级班级(集合)
        /// </summary>
        private FirstGrade? myClass = null;

        /// <summary>
        /// 对班级的依赖
        /// </summary>
        /// <param name="myClassToIterator"></param>
        public FirstGradeAsceIterator(FirstGrade myClassToIterator)
        {
            this.myClass = myClassToIterator;
        }

        private int currentIndex = 0;

        public override object Current()
        {
            return this.myClass[this.currentIndex];
        }

        public override object First()
        {
            return this.myClass[0];
        }

        public override void Next()
        {
            this.currentIndex++;
        }

        public override bool IsDone
        {
            get
            {
                return this.currentIndex == this.myClass.StudentsCount;
            }
        }
    }

    /// <summary>
    /// 按照降序迭代
    /// </summary>
    public class FirstGradeDeAsceIterator : Iterator
    {
        /// <summary>
        /// 关联到需要迭代的一年级班级(集合)
        /// </summary>
        private FirstGrade? myClass = null;

        private int currentIndex;

        /// <summary>
        /// 对班级的依赖
        /// </summary>
        /// <param name="myClassToIterator"></param>
        public FirstGradeDeAsceIterator(FirstGrade myClassToIterator)
        {
            this.myClass = myClassToIterator;
            currentIndex = myClass.StudentsCount - 1;
        }

        public override object Current()
        {
            return this.myClass[this.currentIndex];
        }

        public override object First()
        {
            return this.myClass[myClass.StudentsCount - 1];
        }

        public override void Next()
        {
            this.currentIndex--;
        }

        public override bool IsDone
        {
            get
            {
                return this.currentIndex == -1;
            }
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            FirstGrade firstGrade = new FirstGrade();
            firstGrade.AddStudent(new Student("张三"));
            firstGrade.AddStudent(new Student("李四"));
            firstGrade.AddStudent(new Student("王五"));

            Iterator iterator = (firstGrade as Aggregate).CreateIterator();
            while (!iterator.IsDone)
            {
                object current = iterator.Current();
                Console.WriteLine(current);
                iterator.Next();
            }
            Console.ReadLine();
        }
    }
}
namespace Test
{
    /// <summary>
    /// 聚合对象(集合)
    /// </summary>
    public abstract class Aggregate
    {
        public abstract Iterator CreateIterator();
    }

    /// <summary>
    /// 迭代器:能遍历一个集合的遍历行为
    /// </summary>
    public abstract class Iterator
    {
        public abstract object First();
        public abstract void Next();
        public abstract object Current();
        public abstract bool IsDone
        {
            get;
        }
    }

    /// <summary>
    /// 一年级
    /// </summary>
    public class FirstGrade : Aggregate
    {
        public override Iterator CreateIterator()
        {
            return new FirstGradeAsceIterator(this);
            //return new FirstGradeDeAsceIterator(this);
        }

        private List<Student> students = new List<Student>();
        public void AddStudent(Student student)
        {
            this.students.Add(student);
        }

        /// <summary>
        /// 按照升序迭代
        /// </summary>
        private class FirstGradeAsceIterator : Iterator
        {
            /// <summary>
            /// 关联到需要迭代的一年级班级(集合)
            /// </summary>
            private FirstGrade? myClass = null;

            /// <summary>
            /// 对班级的依赖
            /// </summary>
            /// <param name="myClassToIterator"></param>
            public FirstGradeAsceIterator(FirstGrade myClassToIterator)
            {
                this.myClass = myClassToIterator;
            }

            private int currentIndex = 0;

            public override object Current()
            {
                return this.myClass.students[this.currentIndex];
            }

            public override object First()
            {
                return this.myClass.students[0];
            }

            public override void Next()
            {
                this.currentIndex++;
            }

            public override bool IsDone
            {
                get
                {
                    return this.currentIndex == this.myClass.students.Count;
                }
            }
        }

        /// <summary>
        /// 按照降序迭代
        /// </summary>
        private class FirstGradeDeAsceIterator : Iterator
        {
            /// <summary>
            /// 关联到需要迭代的一年级班级(集合)
            /// </summary>
            private FirstGrade? myClass = null;

            private int currentIndex;

            /// <summary>
            /// 对班级的依赖
            /// </summary>
            /// <param name="myClassToIterator"></param>
            public FirstGradeDeAsceIterator(FirstGrade myClassToIterator)
            {
                this.myClass = myClassToIterator;
                currentIndex = myClass.students.Count - 1;
            }

            public override object Current()
            {
                return this.myClass.students[this.currentIndex];
            }

            public override object First()
            {
                return this.myClass.students[myClass.students.Count - 1];
            }

            public override void Next()
            {
                this.currentIndex--;
            }

            public override bool IsDone
            {
                get
                {
                    return this.currentIndex == -1;
                }
            }
        }
    }

    public class Student
    {
        public Student(string name)
        {
            this.Name = name;
        }

        public string Name { get; set; }
        public override string ToString()
        {
            return this.Name;
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            FirstGrade firstGrade = new FirstGrade();
            firstGrade.AddStudent(new Student("张三"));
            firstGrade.AddStudent(new Student("李四"));
            firstGrade.AddStudent(new Student("王五"));

            Iterator iterator = (firstGrade as Aggregate).CreateIterator();
            while (!iterator.IsDone)
            {
                object current = iterator.Current();
                Console.WriteLine(current);
                iterator.Next();
            }
            Console.ReadLine();
        }
    }
}
using System.Collections;
using System.Collections.Generic;

namespace Test
{
    public class 车上的乘客NET : System.Collections.IEnumerable
    {
        private System.Collections.ArrayList al = new System.Collections.ArrayList();
        public void 上车(string 乘客姓名)
        {
            this.al.Add(乘客姓名);
        }
        public string this[int index]
        {
            get { return this.al[index].ToString(); }
        }
        public int 数量
        {
            get { return this.al.Count; }
        }
        #region IEnumerable 成员
        public System.Collections.IEnumerator GetEnumerator()
        {
            return new ConcreteIteratorNET(this);
        }
        #endregion
    }

    public class 车上的乘客NET2 : System.Collections.IEnumerable
    {
        private System.Collections.ArrayList al = new System.Collections.ArrayList();

        public void 上车(string 乘客姓名)
        {
            this.al.Add(乘客姓名);
        }
        #region IEnumerable 成员

        public System.Collections.IEnumerator GetEnumerator()
        {
            foreach (object var in this.al)
            {
                yield return var;
            }
        }
        #endregion
    }

    public class ConcreteIteratorNET : System.Collections.IEnumerator
    {
        private 车上的乘客NET _乘客们 = null;
        private int 当前第几个 = -1;
        public ConcreteIteratorNET(车上的乘客NET 乘客)
        {
            this._乘客们 = 乘客;
        }
        #region IEnumerator 成员
        public object Current
        {
            get { return this._乘客们[当前第几个]; }
        }
        public bool MoveNext()
        {
            this.当前第几个++;
            return this.当前第几个 < this._乘客们.数量;
        }
        public void Reset()
        {
            this.当前第几个 = -1;
        }
        #endregion
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            车上的乘客NET 隧道六线 = new 车上的乘客NET();
            隧道六线.上车("张三");
            隧道六线.上车("李四");
            隧道六线.上车("王五");
            隧道六线.上车("赵六");
            System.Collections.IEnumerator iterator = 隧道六线.GetEnumerator();

            while (iterator.MoveNext())
            {
                Console.WriteLine("{0},请你买票,谢谢!", iterator.Current);
            }

            Console.ReadLine();
        }
    }
}

八:总结

<1>迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。
<2>迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
<3>迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值