js设计模式总结-迭代器模式
迭代器模式
要解决的问题
迭代器要解决的问题很简单很单纯,就是进行遍历操作。
实现原理
基本所有语言都实现了迭代器,javascript也不例外,如Array.prototype.forEach,for..of..,for..in..,for
迭代器的种类分两种,内部迭代器,外部迭代器。
内部迭代器
内部迭代器的迭代过程对外部是不可控的,内部自己实现迭代过程.比如forEach, jQuery中的$.each
外部迭代器
外部迭代器就相对灵活,可以控制迭代过程,需要显式调用迭代操作.外部迭代器较内部迭代器来说更方便扩展。
外部迭代器的一个实现
// itObj 是被迭代对象,需要包含length属性
var Iterator = function(itObj) {
this.obj = itObj
this.currentItem = 0
this.length = itObj.length
}
Iterator.prototype.next = function() {
if (this.currentItem < this.length) {
this.currentItem++
}
}
Iterator.prototype.getCurrentItem = function() {
return this.obj[this.currentItem]
}
Iterator.prototype.isDone = function() {
return this.currentItem >= this.length
}
var it = new Iterator([1, 2, 3])
console.log(it.getCurrentItem()) // 1
it.next()
console.log(it.getCurrentItem()) // 2
it.next()
console.log(it.getCurrentItem()) // 3
it.next()
console.log(it.getCurrentItem()) // 3
扩展我们的迭代器,实现两个数组的merge函数
//两个迭代器
var it1 = new Iterator([1,3,4,6])
var it2 = new Iterator([2,3,5,7])
var merge = function(it1, it2) {
var tmp = []
// 两个迭代器同时遍历
while(!it1.isDone() && !it2.isDone()) {
if (it1.getCurrentItem() > it2.getCurrentItem()) {
tmp.push(it2.getCurrentItem())
it2.next()
} else if (it1.getCurrentItem() < it2.getCurrentItem()) {
tmp.push(it1.getCurrentItem())
it1.next()
} else {
tmp.push(it1.getCurrentItem())
it1.next()
it2.next()
}
}
// 如果it1没被遍历完,直接push
while(!it1.isDone()) {
tmp.push(it1.getCurrentItem())
it1.next()
}
// 如果it2没被遍历完,直接push
while(!it2.isDone()) {
tmp.push(it2.getCurrentItem())
it2.next()
}
return tmp
}
console.log(merge(it1, it2)) // [1, 2, 3, 4, 5, 6, 7]
可以看到用外部迭代器很容易地控制迭代过程,扩展功能
实践中的应用
一个copy自书上的例子
获取上传对象
未使用迭代器的版本
var getUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload");
} catch (e) {
// IE 上传控件
if (supportFlash()) { // supportFlash 函数未提供
var str = '<object type="application/x-shockwave-flash"></object>';
return $(str).appendTo($('body'));
} else {
var str = '<input name="file" type="file"/>'; // 表单上传
return $(str).appendTo($('body'));
}
}
}
我们看到其中夹杂着try...catch语句和大量的if语句,严重违反了开闭原则。
使用迭代器重构
var getActiveUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload"); //IE上传控件
} catch (e) {
return false;
}
};
var getFlashUploadObj = function() {
if (supportFlash()) {
var str = '<object type="application/x-shockwave-flash"></object>'
return $(str).appendTo($('body'))
}
return false
}
var getFormUploadObj = function() {
var str = '<input name="file" type="file" class="ui-file" />'
return $(str).appendTo($('body'))
}
var iteratorUploadObj = function() {
for (var i = 0, fn; fn = arguments[i++]) {
var uploadObj = fn()
if (uploadObj !== false) {
return uploadObj
}
}
}
var uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj)
重构代码之后,我们可以看到,获取不同上传对象的方法被隔离在各自的函数里互不干扰, try、catch 和 if 分支不再纠缠在一起,使得我们可以很方便地的维护和扩展代码。
js设计模式总结-迭代器模式的更多相关文章
- js设计模式——4.迭代器模式
js设计模式——4.迭代器模式 代码演示 /*js设计模式——迭代器模式*/ class Iterator { constructor(container) { this.list = contain ...
- 浅谈js设计模式之迭代器模式
迭代器模式无非就是循环访问聚合对象中的各个元素.比如 jQuery中的 $.each 函数,其中回调函数中的参数 i 为当前索引, n 为当前元素,代码如下: $.each([1, 2, 3], fu ...
- JS设计模式——5.单体模式
JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html 单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...
- 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)
原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...
- Python进阶:设计模式之迭代器模式
在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...
- 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)
设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...
- js设计模式——7.备忘录模式
js设计模式——7.备忘录模式 /*js设计模式——备忘录模式*/ // 备忘类 class Memento { constructor(content) { this.content = conte ...
- js设计模式——6.模板方法模式与职责链模式
js设计模式——6.模板方法模式与职责链模式 职责链模式
- js设计模式——5.状态模式
js设计模式——5.状态模式 代码演示 /*js设计模式——状态模式*/ // 状态(红灯,黄灯,绿灯) class State { constructor(color) { this.color = ...
随机推荐
- 利用tween.js算法生成缓动效果
在讲tween类之前,不得不提的是贝塞尔曲线了.首先,贝塞尔曲线是指依据四个位置任意的点坐标绘制出的一条光滑曲线.它在作图工具或动画中中运用得比较多,例如PS中的钢笔工具,firework中的画笔等等 ...
- nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 错误解决
今天在做LNMP的时候,启动nginx服务,无法开启,导致网页打不开.把服务从起一下发现提示错误如下: Starting nginx: nginx: [emerg] bind() to 0.0.0.0 ...
- iOS10 - 访问系统通讯录新方法
所需框架 #import <ContactsUI/ContactsUI.h> 遵循代理 CNContactPickerDelegate 调用通讯录 如果在iOS10的机器上调用以前的ABP ...
- ASP.NET MVC EF 中使用异步控制器
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精 为什么使用异步操作/线程池 ASP.NET MVC ...
- jsp+servlet 中文乱码问题
一. 由于doget和dopost的处理方式不同,在做servlet的时候遇到这样一个问题:用doPost获得的参数只要加上“request.setCharacterEncoding("ut ...
- java快速学习
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java是面向对象语言.这门语言其实相当年轻,于1995年才出现,由Sun公司出品 ...
- sed tr 去除PATH中的重复项
最近发现由于自己不良的安装软件的习惯,shell的PATH路径包含了很多冗余的项.这里使用shell命令去除PATH的冗余项. export PATH=$(echo $PATH | sed 's/:/ ...
- css设置图片的透明度
在图片的属性中加上{filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: 0.5;} opacity是 ...
- 论文阅读(Chenyi Chen——【ACCV2016】R-CNN for Small Object Detection)
Chenyi Chen--[ACCV2016]R-CNN for Small Object Detection 目录 作者和相关链接 方法概括 创新点和贡献 方法细节 实验结果 总结与收获点 参考文献 ...
- UIFont的常用字体
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize; 系统默认字体 + (UIFont *)boldSystemFontOfSize:(CGFloat)f ...