热门标签 | 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


推荐阅读
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • EPPlus绘制刻度线的方法及示例代码
    本文介绍了使用EPPlus绘制刻度线的方法,并提供了示例代码。通过ExcelPackage类和List对象,可以实现在Excel中绘制刻度线的功能。具体的方法和示例代码在文章中进行了详细的介绍和演示。 ... [详细]
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社区 版权所有