模式补全
这一节按 八面剖析以理解一个概念 / ljg-learn 的思路整理为 Markdown 版本:先定锚,再用八个方向切开概念,最后压缩成公式、例子、类图和检验题。
定锚
迭代器模式(行为型)的通行定义:在不暴露集合内部结构的前提下,顺序访问集合元素。
常见误解:迭代器不只是 for 循环;它把遍历状态和集合结构解耦。
核心词素:Iterator 来自 iterate,重复前进。它的核心动作是 next。
八刀
历史
它是集合库的基础模式,现代 JavaScript 的 Symbol.iterator 直接内建了这种思想。
辩证
反面是客户端知道集合内部数组、树或链表。更高理解是:遍历是一种协议,不是结构暴露。
现象
你排队取号,只关心下一个是谁,不需要知道队伍底层用数组还是链表存。
语言
Iterator 来自 iterate,重复前进。它的核心动作是 next。
形式
iterator.next() → { value, done }。当遍历需要随机访问或复杂查询时,单一迭代器可能不足。
存在
它让集合保留隐私,也让访问者获得稳定步伐。
美感
它美在节拍:一步一步,集合内部的复杂被 next 的节奏压平。
元反思
行走隐喻容易让人只想线性遍历。换成“游标”隐喻,会更注意当前位置和遍历状态。
内观
我是集合递给你的游标。我知道现在走到哪里,也知道何时结束。你不需要拆开集合看。
八刀共同指向的深层结构:迭代器模式不是为了“炫技”,而是在某个变化点上建立边界,让稳定部分继续稳定,让变化部分有自己的位置。
压缩
公式:迭代器 = 遍历协议 + 内部状态 + 集合封装
一句话:迭代器把“怎么遍历”从集合内部结构里抽出来。
结构图:
Client -> Iterator.next() -> Aggregate items动机/意图
当客户端需要遍历集合,但不应该知道集合底层是数组、树、链表还是分页数据源时,直接暴露内部结构会破坏封装。迭代器模式的意图是提供统一遍历协议,把遍历状态从集合结构中分离出来。
结构/角色
Iterator:迭代器接口,声明next()、hasNext()或语言内置迭代协议。ConcreteIterator:具体迭代器,记录当前位置并访问集合元素。Aggregate:聚合对象,声明创建迭代器的方法。ConcreteAggregate:具体聚合,保存元素集合并返回对应迭代器。Client:客户端通过迭代器顺序访问元素。
典型 UML
classDiagram class Aggregate { <<interface>> +createIterator(): Iterator } class ConcreteAggregate class Iterator { <<interface>> +next() +hasNext(): boolean } class ConcreteIterator { -index: number +next() +hasNext(): boolean } Aggregate <|.. ConcreteAggregate Iterator <|.. ConcreteIterator ConcreteAggregate ..> ConcreteIterator ConcreteIterator --> ConcreteAggregate
使用场景
- 需要隐藏集合内部结构,同时提供顺序访问能力。
- 同一集合需要多种遍历方式。
- 遍历状态不应污染集合对象本身。
- 需要适配语言内置迭代协议,例如 JavaScript 的
Symbol.iterator。
正例:TypeScript
class TaskList implements Iterable<string> {
private tasks: string[] = []
add(task: string) {
this.tasks.push(task)
}
[Symbol.iterator]() {
let index = 0
const tasks = this.tasks
return {
next(): IteratorResult<string> {
if (index < tasks.length) return { value: tasks[index++], done: false }
return { value: undefined, done: true }
},
}
}
}正例:UML 类图
classDiagram class Iterable { <<interface>> +iterator(): Iterator } class Iterator { <<interface>> +next(): Result } class TaskList class TaskIterator Iterable <|.. TaskList Iterator <|.. TaskIterator TaskList ..> TaskIterator
反例:TypeScript
const taskList = { internalArray: ["a", "b"] }
for (let i = 0; i < taskList.internalArray.length; i++) {
console.log(taskList.internalArray[i])
}反例:UML 类图
classDiagram class Client class TaskList { +internalArray: string[] } Client --> TaskList : reads internals
案例
电视机遥控器就是一个迭代器的实例,通过它可以实现对电视机频道集合的遍历操作,本实例我们将模拟电视机遥控器的实现。
掌握检验
- 迭代器如何保护集合内部结构?
- JavaScript 的 Symbol.iterator 如何体现迭代器模式?
- 外部迭代器和内部迭代器有什么区别?