设计模式-大话设计模式总结-行为型->迭代器

点评

迭代器是很好的访问聚集对象的方法,为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。/br 实现迭代器模式的实现,应该把重点放在两个点:/br 1、实现迭代器接口的类方法 2、聚集类存放原始数据,同时有一个方法可以创建出某个迭代器实例(为什么是某个,迭代器可以有多种实现,比如正序的迭代器,倒叙迭代器,某些赛选功能的迭代器等等)。

迭代器在语言中的实现

迭代器在各种高级语言中都以嵌入到语法中,如lua中的选好 for k,v in ipairs(table) do end ;C# 中 foreach (var item in list) { }等等。
而且 .NET的迭代器实现了上述的迭代器接口。 也就是我们不需要设计上述的类方法了。直接使用IEumerator(顶层迭代器抽象上方1) 和 IEnumerable(顶层创建迭代器类上方2)、 C#中foreach语法糖,会被编译器实现未一个while循环语法,以访问迭代器中的元素。

Unity携程中的迭代器

MonoBehaviour.StartCoroutine接收的参数为什么是IEnumerator,IEnumerator和协程有什么关系?

知识点1:迭代器函数

yield是C#的关键字,其实就是快速定义迭代器的语法糖。只要是yield出现在其中的方法就会被编译器自动编译成一个迭代器,对于这样的函数可以称之为迭代器函数。迭代器函数的返回值就是自动生成的迭代器类的一个对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test : MonoBehaviour
{
Animator animator = null;

void Start()
{
IEnumerator enumerator = DoSomeThing();

while(enumerator.MoveNext())
{
Debug.Log("T:"enumerator.Current);
}
}

IEnumerator DoSomeThing()
{
yield return 1;
yield return 2;
yield return 3;
yield return new WaitForSeconds(0.5f);
yield return "haha";
}
}
上方输出是:
T:1
T:2
T:3
T:UnityEngine.WaitForSeconds
T:haha

知识点2:Unity协程机制

下方文字引用一位网友的理解,原理描述得比较清晰!

Unity每通过MonoBehaviour.StartCoroutine启动一个协程,就会获得一个IEnumerator(StartCoroutine的参数就是IEnumerator,参数是方法名的重载版本也会通过反射拿到该方法对应的IEnumerator)。并在它的游戏循环中,根据条件判断是否要执行MoveNext方法。而这个条件就是根据IEnumerator的Current属性获得的,即yield return返回的值。

在启动一个协程时,Unity会先调用得到的IEnumerator的MoveNext一次,以拿到IEnumerator的Current值。所以每启动一个协程,协程函数会立即执行到第一个yield return处然后“停住”。
对于不同的Current类型(一般是YieldInstruction的子类),Unity已做好了一些默认处理,比如:

如果Current是null,就相当于什么也不做。在下一次游戏循环中,就会调用MoveNext。所以yield return null就起到了等待一帧的作用

如果Current是WaitForSeconds类型,Unity会获取它的等待时间,每次游戏循环中都会判断时间是否到了,只有时间到了才会调用MoveNext。所以yield return WaitForSeconds就起到了等待指定时间的作用

如果Current是UnityWebRequestAsyncOperation类型,它是AsyncOperation的子类,而AsyncOperation有isDone属性,表示操作是否完成,只有isDone为true时,Unity才会调用MoveNext。对于UnityWebRequestAsyncOperation而言,只有请求完成了,才会将isDone属性设置为true。

unity文档中的一些参考

untiy官方文档关于执行顺序的一些说明 ExecutionOrder