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 ...
随机推荐
- Kafka 信息整理
请说明什么是传统的消息传递方法? 传统的消息传递方法包括两种: ·排队:在队列中,一组用户可以从服务器中读取消息,每条消息都发送给其中一个人. ·发布-订阅:在这个模型中,消息被广播给所有的用户. 为 ...
- ResNeXt论文阅读笔记.md
目录 1. 提出背景 2. 核心思想 3. 论文核心 4. 分组卷积 5. 核心代码 论文: Aggregated Residual Transformations for Deep Neural N ...
- 【JVM之内存与垃圾回收篇】方法区
方法区 前言 这次所讲述的是运行时数据区的最后一个部分 从线程共享与否的角度来看 ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理,以及会话管理 栈.堆.方法区 ...
- 题解 洛谷 P2046 【[NOI2010]海拔】
首先进行贪心,发现海拔有梯度时一定是不优的,最优的情况是海拔像断崖一样上升,也就是左上角有一片海拔高度为\(0\),右下角有一片海拔高度为\(1\). 发现这样的性质后,不难想到用最小割来解决问题,但 ...
- Redis知识总结
1.什么是Redis Redis是一个nosql(not only sql 不仅仅只有sql)数据库,翻译成中文叫做非关系型数据库,低由C语言开发,数据模型为key-value 关系型数据库:以二维表 ...
- 七牛云如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器?
一般情况下,点账户名——账户设置——安全设置,即可开通两步验证 具体步骤见链接 七牛云如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器? 二次验证码小程序(官网)对比谷歌身份验证器APP ...
- Dicom文件基本操作
官方文档 网址:https://github.com/fo-dicom/fo-dicom托管在github上. 官方例子 Dicom文件基本操作 var file = DicomFile.Open(@ ...
- spring学习(六)注解方式实现AOP
一.导包(导入maven的依赖) <?xml version="1.0" encoding="UTF-8"?> <project xmlns= ...
- 关于android的监听器
import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bu ...
- map,reduce,filter基础实现
#coding=gbk from operator import add # 导入加法 # map 函数名 , 序列对象 print(list(map(str,range(5)))) print(li ...