写点什么

【愚公系列】2022 年 05 月 二十三种设计模式 (十六)- 迭代器模式 (Iterator Pattern)

作者:愚公搬代码
  • 2022 年 5 月 17 日
  • 本文字数:3066 字

    阅读完需:约 10 分钟

前言

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

一、迭代器模式(Iterator Pattern)

迭代器模式属于行为型模式,它提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

二、使用步骤

角色

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 返回一个迭代器的状态机。


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 SmithJim JohnsonSue Rabon---------------------------------------------John SmithJim JohnsonSue 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!---------------------------------------------
复制代码


<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

总结

优点

1、迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象;2、迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

缺点

1、迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用 foreach 语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。

使用场景

1、系统需要访问一个聚合对象的内容而无需暴露它的内部表示;2、系统需要支持对聚合对象的多种遍历;3、系统需要为不同的聚合结构提供一个统一的接口。

发布于: 刚刚阅读数: 2
用户头像

还未添加个人签名 2022.03.01 加入

该博客包括:.NET、Java、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、python、大数据等相关使用及进阶知识。查看博客过程中,如有任何问题,皆可随时沟通。

评论

发布
暂无评论
【愚公系列】2022年05月 二十三种设计模式(十六)-迭代器模式(Iterator Pattern)_5月月更_愚公搬代码_InfoQ写作社区