大家好!本文介绍迭代器模式及其在Javascript中的应用。

模式介绍

定义

提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示。

类图及说明

Iterator抽象迭代器

抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定的3个方法:first()获得第一个元素,next()访问下一个元素,isDone()(或者为hasNext())是否已经访问到底部

ConcreIterator具体迭代器

具体迭代器角色要实现迭代器接口,完成容器元素的遍历。

Aggregate抽象容器

容器角色负重提供创建具体迭代器角色的接口,必然提供一个类似createIterator()(或者为iterator())这样的方法。

Concrete Aggregate具体容器

具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。

应用场景

  • 访问一个聚合对象的内容而无需暴露它的内部表示。

  • 支持对聚合对象的多种遍历。

  • 为遍历不同的聚合结构提供一个统一的接口。

优点

  1. 支持以不同的方式遍历一个聚合,复杂的聚合可用多种方式进行遍历。
  2. 迭代器简化了聚合的接口。有了迭代器的遍历接口,聚合本身就不需要类似的遍历接口了,这样就简化了聚合的接口。
  3. 在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。

缺点

  1. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  2. 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如 JDK 内置迭代器 Iterator 就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类ListIterator 等来实现,而 ListIterator 迭代器无法用于操作 Set 类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

迭代器模式在Javascript中的应用

我的理解

抽象迭代器角色

定义对数据结构的通用基本操作。如hasNext、next等。

具体迭代器角色

实现对某一类数据结构的基本操作。如ArrIterator实现对数组结构的基本操作,hashIterator实现对hash结构的基本操作

容器角色

实现数据结构的特定操作。

类图及说明

介绍两种形式的应用:

继承

优点

  • 容器类可直接复用迭代器的操作,不用再提供方法iterator来获得迭代器实例了。

缺点

  • 容器类继承了迭代器的所有操作,有些操作它可能不会用到。
  • 限定了迭代器的扩展,在修改迭代器时可能会影响到容器类。

适用场合

  • 迭代器比较简单
  • 容器类需要使用所有的迭代器方法

委托

优点

  • 容器类可以只使用迭代器的部分操作。
  • 灵活,便于容器类与迭代器类扩展。

缺点

  • 容器类中需要增加委托方法iterator。

适用场合

  • 迭代器类和容器类需要扩展

示例

大神可以拿各种offer,屌丝表示很是好奇。一天屌丝偷偷搞到了大神读的书籍清单,于是迫不及待地打开,想看个究竟。

类图

代码

代码中使用的库:YOOP

IBook

var IBook = YYC.Interface("showInfo");

Book

    var Book = YYC.Class({Interface: IBook}, {
Init: function (name) {
this._name = name;
},
Private: {
_name: ""
},
Public: {
showInfo: function () {
console.log(this._name);
}
}
});

场景类

    function main(){
//定义一个数组容器,存放所有的书对象
var container, i, len; container = [];
i = ;
len = ; container.push(new Book("设计模式之禅"));
container.push(new Book("Http权威指南"));
container.push(new Book("深入理解计算机操作系统")); for(i = , len = container.length; i < len; i++){
container[i].showInfo();
}
}

运行结果

示例分析

场景类中实现了一个数组容器及其遍历。应该把容器的实现封装起来形成容器类,令场景类调用容器的接口方法。

另外,容器类中访问数组容器元素的逻辑具有通用性,可以提出来形成迭代器类。凡是需要访问数组容器元素的容器类,只要使用迭代器类就可以实现。

使用迭代器模式

现在分别用继承和委托的方式来实现。

继承

可以将内部容器container放到Iterator类中。

类图

代码

IIterator

var IIterator = YYC.Interface("hasNext", "next");

Iterator

var Iterator = YYC.Class({Interface: IIterator}, {
Init: function () {
},
Private: {
_container: [],
_cursor:
},
Public: {
hasNext: function () {
if (this._cursor === this._container.length) {
return false;
}
else {
return true;
}
},
next: function () {
var result = null; if (this.hasNext()) {
result = this._container[this._cursor];
this._cursor += ;
}
else {
result = null;
} return result;
}
}
});

BookContainer

     var BookContainer = YYC.Class(Iterator, {
Init: function(){},
Public: {
add: function(name){
this._container.push(new Book(name));
},
showInfo: function(){
while(this.hasNext()){
this.next().showInfo();
}
}
}
});

IBook

var IBook = YYC.Interface("showInfo");

Book

var Book = YYC.Class({Interface: IBook}, {
Init: function (name) {
this._name = name;
},
Private: {
_name: ""
},
Public: {
showInfo: function () {
console.log(this._name);
}
}
});

场景类Client

function main() {
var container = new BookContainer(); container.add("设计模式之禅");
container.add("Http权威指南");
container.add("深入理解计算机操作系统"); container.showInfo();
}

委托

Iterator中通过注入获得内部容器container。

类图

代码

IIterator

var IIterator = YYC.Interface("hasNext", "next");

Iterator

var Iterator = YYC.Class({Interface: IIterator}, {
Init: function (container) {
this._container = container;
},
Private: {
_container: [],
_cursor:
},
Public: {
hasNext: function () {
if (this._cursor === this._container.length) {
return false;
}
else {
return true;
}
},
next: function () {
var result = null; if (this.hasNext()) {
result = this._container[this._cursor];
this._cursor += ;
}
else {
result = null;
} return result;
}
}
});

IBookContainer

var IBookContainer = YYC.Interface("add", "iterator");

BookContainer

var BookContainer = YYC.Class({ Interface: IBookContainer }, {
Init: function () {
},
Private: {
_container: []
},
Public: {
add: function (name) {
this._container.push(new Book(name));
},
iterator: function () {
return new Iterator(this._container);
}
}
});

IBook

var IBook = YYC.Interface("showInfo");

Book

var Book = YYC.Class({Interface: IBook}, {
Init: function (name) {
this._name = name;
},
Private: {
_name: ""
},
Public: {
showInfo: function () {
console.log(this._name);
}
}
});

场景类Client

function main() {
var container, iter; container = new BookContainer(); container.add("设计模式之禅");
container.add("Http权威指南");
container.add("深入理解计算机操作系统"); iter = container.iterator(); while (iter.hasNext()) {
iter.next().showInfo();
}
}

变形

  上面将容器类BookContainer的showInfo方法放到场景类中实现。也可以将其放到BookContainer中,这样BookContainer就不需要iterator方法了。

IBookContainer

var IBookContainer = YYC.Interface("add", "showInfo");

BookContainer

var BookContainer = YYC.Class({ Interface: IBookContainer }, {
Init: function () {
this._iter = new Iterator(this._container);
},
Private: {
_container: [],
_iter: null
},
Public: {
add: function (name) {
this._container.push(new Book(name));
},
showInfo: function () {
while (this._iter.hasNext()) {
this._iter.next().showInfo();
}
}
}
});

场景类

function main() {
var container = new BookContainer(); container.add("设计模式之禅");
container.add("Http权威指南");
container.add("深入理解计算机操作系统"); container.showInfo();
}

运行结果

示例分析

  为什么add放到容器类BookContainer,而不是放到迭代器Iterator中呢?

add: function (name) {
this._container.push(new Book(name));
},

因为在add方法中需要创建Book实例,因此与容器元素Book强耦合。而Iterator中都是容器的基本操作,是不需要知道具体的容器元素的。所以add不能放到Iterator中。

又因为add属于容器操作,因此应该放到作为容器类的BookContainer中。

参考资料

《设计模式之禅》

迭代器模式

Javascript设计模式之我见:迭代器模式的更多相关文章

  1. javascript设计模式学习之七——迭代器模式

    一.迭代器模式定义 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,并且不需要暴露该对象的内部表示. 在当前大部分语言中,都已经内置了迭代器模式.迭代器有内部迭代器和外部迭代器之分,一般现有语 ...

  2. 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)

      设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的 ...

  3. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

  4. 《Head first设计模式》之迭代器模式

    迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了! 真是个好消息!现在我们可以在同一个地方,享用煎饼屋美味的煎饼早餐,和好吃 ...

  5. javascript设计模式--策略模式

    javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...

  6. JavaScript 设计模式: 发布者-订阅者模式

    JavaScript 设计模式: 发布者-订阅者模式 发布者-订阅者模式 https://github.com/Kelichao/javascript.basics/issues/22 https:/ ...

  7. Javascript设计模式之我见:状态模式

    大家好!本文介绍状态模式及其在Javascript中的应用. 模式介绍 定义 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是控制一个对象状态的条件表达式 ...

  8. javascript设计模式实践之迭代器--具有百叶窗切换图片效果的JQuery插件(一)

    类似于幻灯片的切换效果,有时需要在网页中完成一些图片的自动切换效果,比如广告,宣传,产品介绍之类的,那么单纯的切就没意思了,需要在切换的时候通过一些效果使得切换生动些. 比较常用之一的就是窗帘切换了. ...

  9. 【读书笔记】读《JavaScript设计模式》之代理模式

    一.定义 代理是一个对象,它可以用来控制对另一个对象的访问.它与另外那个对象实现了同样的接口,并且会把任何方法调用传递给那个对象.另外那个对象通常称为本体.代理可以代替其实体被实例化,并使其可被远程访 ...

随机推荐

  1. Dell PowerVault TL4000 磁带机卡带问题

    最近一段时间Dell PowerVault TL4000 磁带机故障频繁,昨天我在管理系统里面看到Library Status告警:HE: sled blocked, error during sle ...

  2. JDK中的并发bug?

    最近研究Java并发,无意中在JDK8的System.console()方法的源码中翻到了下面的一段代码: private static volatile Console cons = null; / ...

  3. 【php】mysql全局ID生成方案

    生产系统随着业务增长总会经历一个业务量由小变大的过程,可扩展性是考量数据库系统高可用性的一个重要指标;在单表/数据库数据量过大,更新量不断飙涨时,MySQL DBA往往会对业务系统提出sharding ...

  4. 问题解决——Group Box控件遮挡其他控件

    转载请保持文章的完整性并显要地注明出处 本文链接:http://blog.csdn.net/wlsgzl/article/details/38042301 ====================== ...

  5. SpringMVC中@ResourceMapping的基本用法

    最近从Struts转投SpringMVC,看代码时发现这个注解,感觉其作用应该和Struts的action差不多,把用法记录下来. 1. @RequestMapping(value="/de ...

  6. [嵌入式开发板]iTOP-4412开发板linux 系统存储空间的修改

    平台:iTOP-4412开发板 这里我们以修改成 1G 存储空间为例来讲解修改方法, 如果需要改 成其他大小的存储空间,参照此方法修改即可. 首先连接好 iTOP-4412 开发板的调试串口到 pc  ...

  7. hadooop 运维之 container error exit code 1

    hadoop container exit code: 1 在执行hadoop的时候,发现nodemanager 进程日志里面有这个错误. 网上搜索,一般找到的都是yarn classspath配置的 ...

  8. Hbase step by step 完全分布式安装

    Step1: download and extract the packages: http://mirror.bit.edu.cn/apache/hbase/stable/ Step2: set t ...

  9. common-pool2对象池(连接池)的介绍及使用

    我们在服务器开发的过程中,往往会有一些对象,它的创建和初始化需要的时间比较长,比如数据库连接,网络IO,大数据对象等.在大量使用这些对象时,如果不采用一些技术优化,就会造成一些不可忽略的性能影响.一种 ...

  10. dipole antenna simulation by HFSS

    工作频点为1GHz,新建工程,添加新设计,编辑添加下面的变量 建立天线模型,即两个金属圆柱.编辑完一个振子后,另一半可以用镜像命令产生参数如下设置 ,材料为PEC 两个圆柱间建立一个矩形片,连接两个圆 ...