zoukankan      html  css  js  c++  java
  • 设计模式之三:迭代器模式(IteratorPattern)

    迭代器(Iterator)模式,又叫游标(Cursor)模式。其定义为:提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式是和容器相关的,对容器对象的访问设计到遍历算法。

    迭代器模式由以下角色组成:

    1. 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。
    2. 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并记录遍历中的当前位置。
    3. 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。
    4. 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口---这个迭代器角色与该容器的结构相关。

    意图:就是提供一种访问集合对象的方法,而又无需暴露该对象的内部细节。

    在.NET中的Iterator模式

       在.NET下实现的Iterator模式,对于聚集接口和迭代器接口已经存在了,其中IEnumerator扮演的就是迭代器的角色。它的代码如下:

    public interface IEnumerator

        {

            object Current

            {

                get;

            }

            void Reset();

            bool MoveNext();

        }

    IEnumerable则扮演的就是抽象聚集的角色,只有一个GetEnumertor()方法。如果集合对象需要具备迭代遍历的功能,就必须实现该接口。

    public interface IEnumerable

        {

            IEnumerator GetEnumerator();

        }

    下面看一个在网上http://www.theserverside.net/看到的.NET1.1下的迭代器例子,我稍微做了修改,Person类是一个可枚举的类。PersonsEnumerator类是一个枚举器类

    public class Persons : IEnumerable

        {

            public string[] m_Names;

            public Persons(string[] names)

            {

                m_Names = new string[names.Length];

                names.CopyTo(m_Names, 0);

            }

            private string this[int index]

            {

                get

                {

                    return m_Names[index];

                }

                set

                {

                    m_Names[index] = value;

                }

            }

            public IEnumerator GetEnumerator()

            {

                return new PersonsEnumerator(this);

            }

        }

        public class PersonsEnumerator : IEnumerator

        {

            private int index = -1;

            private Persons p;

            public PersonsEnumerator(Persons p)

            {

                this.p = p;

            }

            public bool MoveNext()

            {

                if (index < p.m_Names.Length)

                {

                    return true;

                }

                return false;

            }

            public void Reset()

            {

                index = -1;

            }

            public object Current

            {

                get

                {

                    return p.m_Names[index];

                }

            }

        }

    在.NET2.0及以后的版本,由于有了yield return关键字,实现起来就更简单了:

    public class Persons : IEnumerable

        {

            private string[] m_names;

            public Persons(string[] names)

            {

                m_names = new string[names.Length];

                names.CopyTo(m_names,0);

            }

            public IEnumerator GetEnumerator()

            {

                foreach(string name in m_names)

                {

                    yield return name;

                }

            }

    }

    另外顺便简单介绍一下yield关键字:

    关键字yield,在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。迭代器有两个特殊语句:yield return <expression>;

                      Yield break;

    迭代器块

         迭代器块是有一个或多个yield语句的代码库。下面三种类型的代码块中任意一种都可以是迭代器块:

         方法主体

         访问器主体

         运算符主体

    Yield语句只能出现在迭代器块中,该块可用作方法,运算符或访问器的体。这类方法,运算符或访问器的体受以下约束的控制:

    1. 不允许不安全块
    2. 方法,运算符或访问器的参数不能是ref或out
    3. Yield语句不能出现在匿名方法中
    4. Yield return语句不能出在catch块中活含有一个或多个Catch子句的的try块中。

    Yield语句的跌代块可以产生IEnumerator和IEnumerable两种对象:

  • 相关阅读:
    链表--判断一个链表是否为回文结构
    矩阵--“之”字形打印矩阵
    二叉树——平衡二叉树,二叉搜索树,完全二叉树
    链表--反转单向和双向链表
    codeforces 490C. Hacking Cypher 解题报告
    codeforces 490B.Queue 解题报告
    BestCoder19 1001.Alexandra and Prime Numbers(hdu 5108) 解题报告
    codeforces 488A. Giga Tower 解题报告
    codeforces 489C.Given Length and Sum of Digits... 解题报告
    codeforces 489B. BerSU Ball 解题报告
  • 原文地址:https://www.cnblogs.com/shaosks/p/2377428.html
Copyright © 2011-2022 走看看