热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

初涉c#设计模式-IteratorPattern

一、迭代器模式简介(BriefIntroduction)迭代器模式(IteratorPattern),提供一种方法顺序访问一个聚合对象中元素,而不暴露改集合对象的内部表示。Prov

一、迭代器模式简介(Brief Introduction)

  迭代器模式(Iterator Pattern),提供一种方法顺序访问一个聚合对象中元素,而不暴露改集合对象的内部表示。

  Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

二、解决的问题(What To Solve)

      在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种“透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。

  当需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,应该考虑用迭代器模式;当需要对聚集有多种方式遍历时,可以考虑使用迭代器模式。其中,你不用关心到底是什么样子的数组作为对象集合,是Array,是List还是简单的数组,迭代器模式会提供给你一个聚合对象的遍历方式,而不用去了解具体是在遍历什么类型的聚合对象。

三、代码:

View Code
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratePattern
{
    public class Guest
    {
        public string id
        {
            get;
            set;
        }
        public string name
        {
            get;
            set;
        }
        public Guest(string aId, string aName)
        {
            id = aId;
            name = aName;
        }
    }
    public interface IAggrate
    {
        IIterator GetIterator();
    }
    public class ConcreateAggrate:IAggrate
    {
        List<object> _guest = new List<object>();
        public IIterator GetIterator()
        {
            return new ConcreateIterator(this);
        }
        public object this[int index]
        {
            get{return _guest[index];}
            set{_guest.Add(value);}
        }
        public int count()
        {
            return _guest.Count;
        }
    }
    public interface IIterator
    {
        bool Next();

    }
    class ConcreateIterator : IIterator
    {
        ConcreateAggrate _aggrate;
        int currentindex;
        public ConcreateIterator(ConcreateAggrate aAggrate)
        {
            _aggrate = aAggrate;
            currentindex = -1;
        }
        public object Current
        {
            get { return _aggrate[currentindex]; }
        }
        public bool Next()
        {
            currentindex++;
            return _aggrate.count() > currentindex;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ConcreateAggrate aAggrate = new ConcreateAggrate();
            aAggrate[0] = new Guest("1", "hi");
            aAggrate[1] = new Guest("2", "my");
            aAggrate[2] = new Guest("3", "dear");
            aAggrate[3] = new Guest("4", "iterator");
            aAggrate[4] = new Guest("5", "pattern");
            //ConcreateIterator aIterator = new ConcreateIterator(aAggrate);
            ConcreateIterator aIterator = (ConcreateIterator)aAggrate.GetIterator();
            while (aIterator.Next())
                Console.WriteLine(((Guest)aIterator.Current).name);
        }
    }
}

 

举例Iterator应用

image

  下面是迭代器所拥有的最小集合,Current是属性,只能Get不能Set。还有两个方法:MoveNext是往下一个元素走,如果访问到最后一个元素之后没有元素了,就返回False;Reset是复位,回到初始位置。

image

  如果有一个容器实现了IEnumerable接口,它就可以支持我们的迭代操作了。这种设计模式已经内化为C#语言的一种元素了,就是Foreach关键字。我们定义的容器首先要实现IEnumerable接口,实现的GetEnumerator方法要返回一个IEnumerator的类型的集合。

View Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace IteratePattern
{
    public class Guest
    {
        public string id
        {
            get;
            set;
        }
        public string name
        {
            get;
            set;
        }
        public Guest(string aId, string aName)
        {
            id = aId;
            name = aName;
        }
    }
    public class ConcreateAggrate:IEnumerable
    {
        List<object> _guest = new List<object>();
        public object this[int index]
        {
            get{return _guest[index];}
            set{_guest.Add(value);}
        }
        public int count()
        {
            return _guest.Count;
        }

        #region IEnumerable 成员

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new ConcreateIterator(this);
        }

        #endregion
    }
    class ConcreateIterator : IEnumerator
    {
        ConcreateAggrate _aggrate;
        int currentindex;
        public ConcreateIterator(ConcreateAggrate aAggrate)
        {
            _aggrate = aAggrate;
            currentindex = -1;
        }
        #region IEnumerator 成员

        object IEnumerator.Current
        {
            get { return _aggrate[currentindex]; }
        }

        bool IEnumerator.MoveNext()
        {
            currentindex++;
                return _aggrate.count() > currentindex;
        }

        void IEnumerator.Reset()
        {
            currentindex = -1;
        }

        #endregion
    }
    class Program
    {
        static void Main(string[] args)
        {
            ConcreateAggrate aAggrate = new ConcreateAggrate();
            aAggrate[0] = new Guest("1", "hi");
            aAggrate[1] = new Guest("2", "my");
            aAggrate[2] = new Guest("3", "dear");
            aAggrate[3] = new Guest("4", "iterator");
            aAggrate[4] = new Guest("5", "pattern");
            foreach (Guest aGuest in aAggrate)
                Console.WriteLine(aGuest.name);
        }
    }
}

 

  Foreach的工作机制

IEnumerator ietor = aAggrate.GetEnumerator();

while(ietor.MoveNext())

{

  Guest aGuest = (Guest)ietor.Current;

 Console.WriteLine(aGuest);

}

 

 

遍历代码中访问的全部是接口,而不用关心集合的内部结构。上面的代码等同于下面的Foreach。

image

结构(Structure)

 

Iterator模式的几个要点

  迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。例如假设我们有一个求和算法

image

  它可以操作在多个支持迭代器的集合上,如果把这个算法写成ArrayList的话,就会非常受限制。同时我们更可以用C#的Foreach语句来写。

image

  我们的算法应该是独立的,写的时候应该尽量操作接口,这样我们写好一个算法,就能应对N种集合的变化,使得同样的算法能在不同的集合上操作。迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。也就是说,我们在迭代的时候,应该只是读取操作,不能更改容器的接口,例如遍历的时候删除一个元素,这样是不可以的。容器的结构师绝对不能碰的,一旦结构更改,遍历就会出问题。

image

  下面这种情况对i进行更改,是不会影响原来的数组内容的,因为i是int类型,它只是一份拷贝。

image

image

  我们一定要给用户提供尽量纯只读的迭代。保证每个元素被且只被遍历一次。

(引自:山天大畜博客园,http://www.cnblogs.com/cdts_change/archive/2010/10/17/1853689.html)

总结(Conclusion)

从上面的几个示例中就可以看出,尽管我们没有显示的引用迭代器,但实质还是通过迭代器来遍历的。总地来说,迭代器模式就是分离了集合对象的迭代行为,抽象出一个迭代器类来负责,这样既可做到不暴露集合的内部结构,又可以让外部代码可以透明的访问集合内部的元素。

  迭代器模式在访问数组、集合、列表等数据时,尤其是数据库数据操作时,是非常普遍的应用,但由于它太普遍了,所以各种高级语言都对他进行了封装,所以反而给人感觉此模式本身不太常用了。

 

转载请注明出处:Edward_jie,http://www.cnblogs.com/promise-7/archive/2012/05/28/2521918.html


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 怀疑是每次都在新建文件,具体代码如下 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
王晓东
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有