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.对扩展开放,对修改 ...
随机推荐
- python 函数及变量作用域及装饰器decorator @详解
一.函数及变量的作用 在python程序中,函数都会创建一个新的作用域,又称为命名空间,当函数遇到变量时,Python就会到该函数的命名空间来寻找变量,因为Python一切都是对象,而在命名空间中 ...
- dip vs di vs ioc
https://stackoverflow.com/questions/6766056/dip-vs-di-vs-ioc https://docs.microsoft.com/en-us/aspnet ...
- 面象对象设计原则之一:单一职责原则(Single Responsibility Principle, SRP)
单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小.单一职责原则定义如下:单一职责原则(Single Responsibility Principle, SRP):一个类只负责一个功能领域 ...
- Java中的浮点型(Double&Float)计算问题
在刚刚做完的一个项目中,遇到了double型计算不精确的问题.到网上查找后,问题得到解决.经验共享,在这里总结一下. Java中的浮点数类型float和double不能够进行精确运算.这个问题有时候非 ...
- Ubuntu 16.04安装Maven
此篇为http://www.cnblogs.com/EasonJim/p/7139275.html的分支页. 前提:必须正确安装JDK. 一.通过二进制包(tar.gz)安装 下载: 进入下载列表:h ...
- BZOJ3282Tree——LCT
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作. 操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和. 保证x到y ...
- BZOJ2159 Crash的文明世界(树形dp+斯特林数)
根据组合意义,有nk=ΣC(n,i)*i!*S(k,i) (i=0~k),即将k个有标号球放进n个有标号盒子的方案数=在n个盒子中选i个将k个有标号球放入并且每个盒子至少有一个球. 回到本题,可以令f ...
- The Shortest Statement CodeForces - 1051F(待测试)
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- linux异常处理:selinux配置错误导致无法重启
点击返回自学Linux集锦 linux异常处理:selinux配置错误导致无法重启 一次linux无法重启异常记录: 当时第一反应就是梳理最近的配置变更,特别是能预知相关的就是selinux配置变更. ...
- 【ARC065E】??
Description 链接 Solution 问题其实就是从一个点出发,每次可以走与其曼哈顿距离恰好为一个常数\(d\)的点 显然不可能一一走完所有的边,这样复杂度下界至少是\(O(ans)\) 我 ...