迭代器模式在对象集合内部实现未知的情况下,为类型不同的对象集合提供统一的遍历迭代方法。
问题场景
《HF》的例子:早餐店和咖啡店合并,需要统一菜单。
早餐店的菜单使用 ArrayList,咖啡店菜单使用数组。统一菜单时,需要用两个 for 循环调用不同的 API 实现。
有什么设计方法,能够在统一菜单时,无需知道菜单各自内部的数据结构,直接统一遍历合并菜单?提供一个统一的「迭代器」接口。
让两种菜单都实现统一的迭代器接口。需要创建菜单的用户只需要调用迭代器 api,合并菜单就 ok 了。

代码实现
只实现了一个用数组存菜单项的早餐菜单:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
 * 迭代器接口
 */
class Iterator {
    // get next item in collection
    next() {}
    // is there next item in collection
    hasNext() {}
}
class BreakfastMenuIterator extends Iterator {
    constructor(list) {
        super();
        this.list = list;
        this.position = 0; // current iterate position in the list
    }
    next() {
        if (this.hasNext()) return this.list[this.position++];
    }
    hasNext() {
        return this.position < this.list.length;
    }
}
/**
 * 菜单接口
 */
class Menu {
    addMenuItem(name, price) {}
}
/**
 * 只实现一个菜单意思一下
 */
class MenuItem {
    constructor(name, price) {
        // 忽略 get 函数,简化代码
        // 直接用 this.[prop] 拿值
        this.name = name;
        this.price = price;
    }
}
class BreakfastMenu extends Menu {
    constructor(list) {
        super();
        this.list = list || new Array();
    }
    createIterator() {
        return new BreakfastMenuIterator(this.list);
    }
    addMenuItem(name, price) {
        this.list.push(new MenuItem(name, price));
    }
}
/**
 * User code
 */
// create menu
let breakfastMenu = new BreakfastMenu();
breakfastMenu.addMenuItem('肉', '¥10');
breakfastMenu.addMenuItem('菜', '¥8');
// print menu
let iterator = breakfastMenu.createIterator();
console.log('----------');
while (iterator.hasNext()) {
    let item = iterator.next();
    console.log(`菜名:${item.name}\n价格:${item.price}`);
    console.log('----------');
}
输出结果:
1
2
3
4
5
6
7
----------
菜名:肉
价格:¥10
----------
菜名:菜
价格:¥8
----------
现实应用
- 各种编程语言代码库的提供的数据结构的迭代器对象。比如 C++,<vector>的迭代器对象由其成员函数begin()和end()返回。
参考资料
- Youtube: iterator pattern
- 《Head First 设计模式》第九章
