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两种对象:

  • 相关阅读:
    JDBC连接效率问题
    如何配置Filter过滤器处理JSP中文乱码(转)
    Servlet生命周期与工作原理(转)
    ANR触发原理
    SystemServer概述
    Zygote总结
    ART、JIT、AOT、Dalvik之间有什么关系?
    谈谈android缓存文件
    Activity启动过程全解析
    tombstone问题分析
  • 原文地址:https://www.cnblogs.com/mamxfx/p/7148096.html
Copyright © 2011-2022 走看看