C#设计模式之16-迭代器模式
迭代器模式(Iterator Pattern)
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/417 访问。
迭代器模式属于行为型模式,它提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
角色:
1、迭代器(Iterator)
迭代器角色负责定义访问和遍历元素的接口;
2、具体迭代器(Concrete Iteraror)
具体迭代器角色实现了迭代器接口,并需要记录遍历中的当前位置;
3、聚合(Aggregate)
聚合角色负责定义获得迭代器角色的接口;
4、具体聚合(Concrete Aggregate)
具体聚合角色实现聚合角色接口。
示例:
命名空间IteratorPattern中包含Person基类、People类、PelpleEnum类,另外包含一个苹果手机ApplePhone类,和BestEnum类。Person示例来自微软官方的IEnumerable接口介绍页面,BestEnum则使用.Net 2.0中的yield return关键字创建苹果手机信息序列。
namespace IteratorPattern
一、传统迭代器实现
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName) {
this.FirstName = firstName;
this.LastName = lastName;
}
}
Person类,包含First Name和Last Name。
public class People : IEnumerable {
private Person[] _people = null;
public People(Person[] pArray) {
_people = new Person[pArray.Length];
for (int i = 0; i < pArray.Length; i++) {
_people[i] = pArray[i];
}
}
public IEnumerator GetEnumerator() {
return new PeopleEnum(_people);
}
}
People类,实现IEnumerable接口。
public class PeopleEnum : IEnumerator {
private Person[] _people = null;
private int _cursor = -1;
public PeopleEnum(Person[] list) {
_people = list;
}
public bool MoveNext() {
_cursor++;
return (_cursor < _people.Length);
}
public void Reset() {
_cursor = -1;
}
public object Current {
get {
try {
return _people[_cursor];
}
catch (IndexOutOfRangeException) {
throw new InvalidOperationException();
}
}
}
}
PeopleEnum类,实现IEnumerator接口。
二、yield return迭代器实现
yield关键字向编译器指示它所在的方法是迭代器块,yield return返回一个迭代器的状态机。
C#开发笔记之05-迭代器中的状态机(State Machine)到底是什么?
public class ApplePhone {
public string PhoneName { get; set; }
public DateTime PublishedDate { get; set; }
}
ApplePhone类,包含手机名称和发布日期。
public class BestEnum {
public static IEnumerable<ApplePhone> GetIPhones() {
yield return new ApplePhone {
PhoneName = "IPhone",
PublishedDate = new DateTime(2007, 1, 9)
};
yield return new ApplePhone {
PhoneName = "IPhone 3G",
PublishedDate = new DateTime(2008, 6, 10)
};
yield return new ApplePhone {
PhoneName = "IPhone 3GS",
PublishedDate = new DateTime(2009, 6, 9)
};
yield return new ApplePhone {
PhoneName = "IPhone 4",
PublishedDate = new DateTime(2010, 6, 8)
};
//部分代码已省略
}
}
BestEnum类,包含GetIPhones方法返回苹果手机信息的序列。
public class Program {
protected const string LINE_BREAK =
"---------------------------------------------";
public static void Main(string[] args) {
var peopleArray = new Person[]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon")
};
var peopleList = new People(peopleArray);
foreach(Person p in peopleList)
Console.WriteLine(p.FirstName + " " + p.LastName);
Console.WriteLine(LINE_BREAK);
var iterator = peopleList.GetEnumerator();
while(iterator.MoveNext()) {
var person = iterator.Current as Person;
Console.WriteLine(person.FirstName + " " + person.LastName);
}
Console.WriteLine(LINE_BREAK);
foreach(var phone in BestEnum.GetIPhones()) {
Console.WriteLine("[" + phone.PhoneName + "] was released in " +
phone.PublishedDate.ToString("yyyy-MM-dd") + "!");
}
Console.WriteLine(LINE_BREAK);
Console.ReadKey();
}
}
以上是调用方的代码,以下是这个案例的输出结果:
John Smith
Jim Johnson
Sue Rabon
---------------------------------------------
John Smith
Jim Johnson
Sue Rabon
---------------------------------------------
[IPhone] was released in 2007-01-09!
[IPhone 3G] was released in 2008-06-10!
[IPhone 3GS] was released in 2009-06-09!
[IPhone 4] was released in 2010-06-08!
[IPhone 4s] was released in 2011-10-04!
[IPhone 5] was released in 2012-09-13!
[IPhone 5S] was released in 2013-09-10!
[IPhone 5C] was released in 2013-09-10!
[IPhone 6] was released in 2014-09-10!
[IPhone 6 Plus] was released in 2014-09-10!
[IPhone 6s] was released in 2015-09-10!
[IPhone 6s Plus] was released in 2015-09-10!
[IPhone 7] was released in 2016-09-08!
[IPhone 7 Plus] was released in 2016-09-08!
[IPhone 8] was released in 2017-09-13!
[IPhone 8 Plus] was released in 2017-09-13!
[IPhone X] was released in 2017-09-13!
---------------------------------------------
优点:
该文章的最新版本已迁移至个人博客【比特飞】,单击链接 https://www.byteflying.com/archives/417 访问。
1、迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象;
2、迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
缺点:
1、迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用foreach语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。
使用场景:
1、系统需要访问一个聚合对象的内容而无需暴露它的内部表示;
2、系统需要支持对聚合对象的多种遍历;
3、系统需要为不同的聚合结构提供一个统一的接口。
C#设计模式之16-迭代器模式的更多相关文章
- 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)
设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的 ...
- 《Head first设计模式》之迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了! 真是个好消息!现在我们可以在同一个地方,享用煎饼屋美味的煎饼早餐,和好吃 ...
- [设计模式] 16 迭代器模式 Iterator Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对迭代器模式是这样说的:提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示. 类图和实例: 迭代器模式由以下角 ...
- C#设计模式(16)——迭代器模式(Iterator Pattern)
一.引言 在上篇博文中分享了我对命令模式的理解,命令模式主要是把行为进行抽象成命令,使得请求者的行为和接受者的行为形成低耦合.在一章中,将介绍一下迭代器模式.下面废话不多说了,直接进入本博文的主题. ...
- 设计模式のIteratorPattern(迭代器模式)----行为模式
一.产生背景 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式.这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示. 二.实现方式 ...
- Java设计模式学习记录-迭代器模式
前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...
- 大话设计模式Python实现-迭代器模式
迭代器模式(Iterator Pattern):提供方法顺序访问一个聚合对象中各元素,而又不暴露该对象的内部表示. 下面是一个迭代器模式的demo: #!/usr/bin/env python # - ...
- 设计模式系列之迭代器模式(Iterator Pattern)——遍历聚合对象中的元素
模式概述 模式定义 模式结构图 模式伪代码 模式改进 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修 ...
- 重学 Java 设计模式:实战迭代器模式「模拟公司组织架构树结构关系,深度迭代遍历人员信息输出场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 相信相信的力量! 从懵懂的少年,到拿起键盘,可以写一个Hell ...
- C#设计模式系列:迭代器模式(Iterator)
迭代器模式把对象的职责分离,职责分离可以最大限度减少彼此之间的耦合程度,从而建立一个松耦合的对象.职责分离的要点是对被分离的职责进行封装,并以抽象的方式建立彼此之间的关系. 1.迭代器模式简介 1.1 ...
随机推荐
- SpringBoot代码生成器
Code-Generate 代码生成器 简介 一个基于原生Mysql & SpringBoot & Mybatis 的代码生成器,建表之后即可完全解放双手,适合: 规律性定制化开发 解 ...
- [Qt2D绘图]-04绘制文字&&绘制路径
注:学习自<Qt Creator 快速入门>第三版. 文档中的示例参考 Qt Example推荐:Painter Paths Example和Vector Deformation ...
- Burp Suite Report - 报告功能
1. 通过点击Host选择不同的颜色,可以设置严重性: 2.生成网页版应用分析报告:选中所有条目->右击网址,保存所有选中项目,存储格式为html.
- 解决win10安装flask-mysqldb报错 Python2.7
win10上安装的pycharm,在pycharm创建的py2.7虚拟环境中安装flask-sqlalchemy 执行pip install flask-mysqldb报错 error: Micros ...
- vue学习(二) 三个指令v-cloak v-text v-html
//style <style> [v-cloak]{ display:none } </style> //html <div id="app"> ...
- 毫无基础的人入门Python,Python新手入门教程2
1.6 面向对象和内存分析086.面向对象和面向过程的区别_执行者思维_设计者思维087.对象的进化故事088.类的定义_类和对象的关系089.构造函数__init__090.实例属性_内存分析091 ...
- Day17_购物车
学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 注:实验 ...
- TCP 服务器端
""" 建立tcp服务器 绑定本地服务器信息(ip地址,端口号) 进行监听 获取监听数据(监听到的客户端和地址) 使用监听到的客户端client_socket获取数据 输 ...
- 把项目从码云上clone到IntelliJ IDEA
前期工作:安装并已配置好git,并且IDEA已经配置好git了 操作如下: 1) 在IDEA启动页面选择Get from Version Control 2) 打开码云上想要clon ...
- Android JNI之动态注册
所谓动态注册,就是不用像静态注册那样按规则严格的命名native方法,而是在加载so库的时候完成这个从Java方法到native方法的匹配工作,而这个匹配工作,需要我们写native代码来完成.下面直 ...