设计模式之迭代器模式
1. 定义
在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素
2. 口语化表述
假设某学校通知全校师生做核酸检测,要求应检尽检(即,每个人都要做)
现在,做核酸监测的工作人员已经到达现场,要求全校师生有序来检测
医护人员当然不知道全校师生怎么排序的,只关注每个人依次做检测并且要所有人都要检测过(即,遍历)
此时全校师生会在校方管理人员的规划下,划分检测顺序,依次做核酸检测
这就是迭代器模式,外来的核酸检测人员无需知道全校师生是怎么排序的,但是能每一个人都有序检测了
(下面的表述会沿用这个场景)
3. 源码示例
迭代器在编程语言中非常常见,例如在JavaScript中,遍历一个数组,最基础的做法就是对数组从头数到尾
let arr = [1, 2, 3]
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
// do something
}
那,遍历一个不好数的对象呢?比如,Map
Map对象可以看成一个一个的键值对,理应可以遍历,但是从外部来说,难以依次操作每一个键值对
能不能Map对象自身实现一个遍历函数呢?当然可以
查阅MDN文档:Map
可以知道,Map对象实现了可迭代协议,对外暴露出了遍历方法
实现了可迭代协议就是可迭代对象,可以使用for...of
循环进行遍历,例如下面的官方示例代码
const map1 = new Map()
map1.set('0', 'foo')
map1.set(1, 'bar')
const iterator1 = map1[Symbol.iterator]()
for (const item of iterator1) {
console.log(item)
// do something
}
// Expected output: Array ["0", "foo"]
// Expected output: Array [1, "bar"]
所以,封装一个对象时,如果后续需要涉及遍历操作,可以考虑使用迭代器模式,封装为可迭代对象
JavaScript. 总结
4.1 设计优点
-
开闭原则
假如有另外的核酸检测人员来了,全校师生的排序规则无需改变
-
单一职责原则
核酸检测人员、全校师生只负责做自己的事情
4.2 适用场景
-
复杂的数据结构,隐藏其复杂性(出于使用便利性或安全性的考虑)
-
遍历不同的甚至是无法预知的数据结构
JavaScript代码中,只要实现了可迭代协议的对象,都可以使用
for...of
循环进行遍历,不管是什么样的数据结构