C#设计模式(15)——迭代器模式
1.迭代器模式介绍
迭代器模式主要用于遍历聚合对象,将聚合对象的遍历行为分离出来,抽象为一个迭代器来负责。迭代器模式用的十分普遍,C#/JAVA等高级语言都对迭代器进行了封装用于遍历数组,集合,列表等,因为各种高级语言都对这种模式做了很好的封装,所以这种模式的使用价值远大于它的学习价值,MartinFlower甚至在网站上提出过撤销这个设计模式,所以这里不打算介绍迭代器模式的概念和原理,而是介绍C#中的迭代器模式应用:C#中的枚举器和迭代器。
2、枚举器和可枚举类型
先看一个简单的例子:
static void Main(string[] args)
{
int[] arr = { ,,,};
foreach (int item in arr)
{
Console.WriteLine("item's Value is :{0}",item);
}
Console.ReadKey();
}
为什么数组能够通过foreach遍历呢?原因是数组实现了IEnumerable接口,IEumerable接口中只有一个成员方法:GetEnumerator(),这个方法返回一个枚举器对象,这个枚举器就是迭代器模式中的迭代器。枚举器可以依次返回请求中数组中的元素,它知道元素的顺序并跟踪元素在序列中的位置,然后返回请求的当前项,我们可以通过GetEnumerator方法获取枚举器对象。那么什么是枚举器呢?实现IEnumerator接口的类型就是枚举器,该接口有三个成员:
current :获取当前位置元素
MoveNext() :把枚举器位置前进到下一项,返回bool,表示位置是否有效(如果没有下一项返回false)
Reset() :把位置重置为原始状态的位置(有索引是一般为-1)
我们重新实现上边例子的foreach操作:
static void Main(string[] args)
{
int[] arr = { ,,,};
//获取arr的枚举器
IEnumerator ie = arr.GetEnumerator();
while (ie.MoveNext())
{
int i = (int)ie.Current;
Console.WriteLine("item's value is:{0}",i);
}
Console.ReadKey();
}
知道了foreach内部是怎么运行的后,我们就可以自己实现一个可以用foreach遍历的类了:自定义的类要实现IEnumerable接口的GetEnumerator方法,这个方法返回一个枚举器(就是一个继承IEnumerator接口的类型),以遍历自定义颜色集合为例,代码如下:
class Program
{
static void Main(string[] args)
{
ColorList colors = new ColorList();
//foreach遍历自定义的类型
foreach (var item in colors)
{
Console.WriteLine(item);
} Console.ReadKey(); } /// <summary>
/// 自定义类 ColorList实现IEnumerable接口
/// </summary>
public class ColorList : IEnumerable
{
//实现GetEnumerator接口方法
public IEnumerator GetEnumerator()
{
return new ColorEnumrator(new string[]{ "red", "blue", "green", "pink" });
}
}
/// <summary>
/// 自定义枚举器
/// </summary>
public class ColorEnumrator : IEnumerator
{
string[] _colors;
//位置索引
private int _position = -;
//枚举器构造方法
public ColorEnumrator(string[] theColors)
{
_colors = new string[theColors.Length];
for (int i = ; i < theColors.Length; i++)
{
_colors[i] = theColors[i];
}
}
//获取当前项的值
public object Current
{
get
{
if (_position < || _position > _colors.Length)
{
throw new Exception("超过边界了!");
}
return _colors[_position];
}
}
//指向下一项
public bool MoveNext()
{
if (_position<_colors.Length-)
{
_position++;
return true;
}
return false;
}
//复位
public void Reset()
{
_position = -;
}
}
}
程序运行结果如下:

总结:可枚举类型是实现了IEnumerable接口的类,IEnumerable接口只有一个成员GetEnumerator方法,用于获取枚举器(实现IEnumerator接口的实例)。
3.迭代器
通过手动实现IEnumerable接口的IEnumerator方法我们已经可以实现自定义可枚举类型了,在C#2.0中提供了更简单的创建可枚举类型的方式:迭代器。我们使用迭代器时,不用我们自己去手动创建IEnumerator实例,编译器会自动帮我们生成IEnumerator内部的Current,MoveNext和Reset方法。使用迭代器上边的例子可以简化为:
class Program
{
static void Main(string[] args)
{
ColorList colors = new ColorList();
//foreach遍历自定义的ColorList类型
foreach (var item in colors)
{
Console.WriteLine(item);
}
Console.ReadKey(); } } /// <summary>
/// 自定义颜色集合,实现IEnumerable接口
/// </summary>
public class ColorList : IEnumerable
{
//实现GetEnumerator接口方法
public IEnumerator GetEnumerator()
{
string[] colors= { "red", "green", "blue", "pink" };
for (int i = ; i < colors.Length; i++)
{
//yield return的作用是指定下一项的内容
yield return colors[i];
} //想反向遍历时可以这样写
//for (int i = colors.Length-1; i >=0; i--)
//{
// yield return colors[i];
//}
}
}
程序运行结果和手动写Enumerator的例子一致,我们可以看出使用迭代器来生成可枚举类型要简单很多,这并不是创建迭代器的过程简单了,而是微软让编译器帮我们自动生成了IEnumerator中的current,MoveNext(),Reset()等内容。
C#设计模式(15)——迭代器模式的更多相关文章
- Python进阶:设计模式之迭代器模式
在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...
- c++设计模式15 --组合模式
今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- js设计模式——4.迭代器模式
js设计模式——4.迭代器模式 代码演示 /*js设计模式——迭代器模式*/ class Iterator { constructor(container) { this.list = contain ...
- 实践GoF的设计模式:迭代器模式
摘要:迭代器模式主要用在访问对象集合的场景,能够向客户端隐藏集合的实现细节. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:迭代器模式>,作者:元闰子. 简介 有时会遇到这 ...
- C#设计模式学习笔记:(15)迭代器模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7903617.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第三个模式--迭 ...
- 设计模式之迭代器模式(Iterator)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- 设计模式(8) - 迭代器模式(iterator)- 实现ArrayList和linkedList的迭代器
上周六就開始写这篇博客,之后一直耽误了.到前天才開始写.今天醒的早,就把这部分整理一下. 本文内容參考易学设计模式和马士兵的迭代器模式的视频. 了解迭代器模式一个作用就是让你在使用 迭代器遍历集合类的 ...
- Head First 设计模式 --9 迭代器模式 组合模式
迭代器模式:提供一种方法书序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 用到的设计原则:1.封装变化2.多用组合,少用继承|3.针对接口编程,不针对实现编程4.松耦合5.对扩展开放,对修改 ...
随机推荐
- 实验十一 团队作业7—团队项目设计完善&编码测试
实验十一 团队作业7—团队项目设计完善&编码测试 实验时间 2018-6-8 Deadline: 2018-6-20 10:00,以团队随笔博文提交至班级博客的时间为准. 评分标准: 按时交 ...
- Odoo中连接mysql数据库
how to integrate Odoo with MySQL - Stack Overflowhttps://stackoverflow.com/questions/31959919/how-to ...
- React 组件
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...
- Bootstrap媒体对象
前面的话 在Web页面或者说移动页面制作中,常常看到图文混排效果,图片居左(或居右),内容居右(或居左)排列.常常把这样的效果称为媒体对象.可以说它是一种抽象的样式,可以用来构建不同类型的组件.本文将 ...
- mybatis 缓存(cache)的使用
许多应用程序,为了提高性能而增加缓存, 特别是从数据库中获取的数据. 在默认情况下,mybatis 的一级缓存是默认开启的.类似于hibernate, 所谓一级缓存,也就是基于同一个sqlsessio ...
- BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)
某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...
- json_encode转化为数组时带下标
//错误 data[$i]=[date("y-m-d H:i:s"),数据查询] //正确 data[]=[date("y-m-d H:i:s"),数据查询] ...
- day29 __eq__ 比较
本质上 "==" 调用的内部方法就是 __eq__() 正常情况下,两个名字相同的变量比较的是内存地址,内存地址当然是不一样的可以使用__eq__来改变成名字相同就相等 1 cla ...
- BZOJ 5249: [2018多省省队联测]IIIDX(贪心 + 线段树)
题意 这一天,\(\mathrm{Konano}\) 接到了一个任务,他需要给正在制作中的游戏 \(\mathrm{<IIIDX>}\) 安排曲目 的解锁顺序.游戏内共有\(n\) 首曲目 ...
- Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)
Libre 6012 「网络流 24 题」分配问题 (网络流,费用流) Description 有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为\(c_{ij}\).试设计一个将n件工作分 ...