迭代器模式
迭代器模式Iterator Pattern
提供了一种方法顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部实现,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据,迭代器模式属于行为型模式。
描述
迭代器模式是针对集合对象而生的,对于集合对象而言,肯定会涉及到对集合的添加和删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作放在集合对象中,但这样的话,集合对象既承担太多的责任了,面向对象设计原则中有一条就是单一职责原则,所有我们要尽可能地分离这些职责,用不同的类取承担不同的责任,迭代器模式就是用迭代器类来承担遍历集合的职责。
优点
- 支持以不同的方式遍历一个聚合对象,并可以简化聚合类。
- 在同一个聚合上可以有多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
- 迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象。
- 迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。
缺点
- 迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
- 迭代器模式在遍历的同时更改迭代器所在的集合结构可能会导致出现异常,不能在遍历的同时更改集合中的元素数量。
适用环境
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 需要为聚合对象提供多种遍历方式。
- 为遍历不同的聚合结构提供一个统一的接口。
实现
// 广播电台示例
class RadioStation { // 电台
constructor(frequency) {
this.frequency = frequency;
}
getFrequency() {
return this.frequency;
}
}
class StationList { // 迭代器
constructor(){
this.index = -1;
this.stations = [];
}
get(i){
return this.stations[this.index];
}
hasNext(){
let index = this.index + 1;
return this.stations[index] !== void 0;
}
next(){
return this.stations[++this.index];
}
addStation(station) {
this.stations.push(station);
}
removeStation(toRemove) {
const toRemoveFrequency = toRemove.getFrequency();
this.stations = this.stations.filter(station => station.getFrequency() !== toRemoveFrequency);
}
}
(function(){
const stationList = new StationList();
stationList.addStation(new RadioStation(89));
stationList.addStation(new RadioStation(101));
stationList.addStation(new RadioStation(102));
stationList.addStation(new RadioStation(103.2));
stationList.stations.forEach(station => console.log(station.getFrequency())); // 89 101 102 103.2
stationList.removeStation(new RadioStation(89));
while(stationList.hasNext()) console.log(stationList.next().getFrequency()); // 101 102 103.2
})();
每日一题
https://github.com/WindrunnerMax/EveryDay
参考
https://www.cnblogs.com/xuwendong/p/9898030.html
https://www.runoob.com/design-pattern/iterator-pattern.html
https://github.com/sohamkamani/javascript-design-patterns-for-humans#-iterator