《JavaScript设计模式与开发实践》读书笔记之享元模式
1. 享元模式
享元模式是一种用于性能优化的模式,享元模式的核心是运用共享技术来有效支持大量细粒度的对象
1.1 传统的文件上传方法
以文件上传为例,文件上传功能可以选择依照队列,一个一个的排队上传,也支持同时选择2000个文件。
假如每一个文件都对应着一个JavaScript上传对象的创建,2000个文件就会同时创建2000个upload对象
假设这里的文件上传支持插件和flash两种
var id=0;
window.startUpload=function(uploadType,files){//uploadType区分是控件还是flash
for(var i=0,file;file=files[i++];){
var uploadObj=new Upload(uploadType,file.fileName,file.fileSize);
uploadObj.init(id++);//给upload对象设置一个唯一的id
}
}; var Upload=function(uploadType,fileName,fileSize){
this.uploadType=uploadType;
this.fileName=fileName;
this.fileSize=fileSize;
this.dom=null;
}; Upload.prototype.init=function(id){
var that=this;
this.id=id;
this.dom=document.createElement('div');
this.dom.innerHTML=
'<span>文件名称:'+this.fileName+',文件大小:'+this.fileSize+'</span>'
+'<button class="delFile">删除</button>';
this.dom.querySelector('.delFile').onclick=function(){
that.delFile();
};
document.body.appendChild(this.dom);
}; Upload.prototype.delFile=function(){
return this.dom.parentNode.removeChild(this.dom);
};
接下来分别创建3个插件上传对象和3个flash上传对象
startUpload('plugin',[
{
fileName:'1.txt',
fileSize:1000
},
{
fileName:'2.html',
fileSize:3000
},
{
fileName:'3.txt',
fileSize:5000
}
]);
startUpload('flash',[
{
fileName:'4.txt',
fileSize:1000
},
{
fileName:'5.html',
fileSize:3000
},
{
fileName:'6.txt',
fileSize:5000
}
]);
这里一共有6个需要上传的文件,一共创建了6个upload对象
1.2 享元模式重构文件上传
划分内部状态和外部状态的关键主要有以下几点
- 内部状态储存于对象内部
- 内部状态可以被一些对象共享
- 内部状态独立于具体的场景,通常不会改变
- 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享
首先,需要确认插件类型uploadType是内部状态
upload对象必须依赖uploadType属性才能工作,因为插件上传、flash上传各自调用的接口是完全不一样的
fileName和fileSize是根据场景而变化,每个文件的fileName和fileSize都不一样,fileName和fileSize没有办法被共享,它们是外部状态
剥离外部状态
var Upload=function(uploadType){
this.uploadType=uploadType;
};
Upload.prototype.init函数不再需要,upload对象初始化工作被放在后面定义的uploadManager.add函数里面
接下来只需要定义Upload.prototype.delFile函数
Upload.prototype.delFile=function(id){
uploadManager.setExternalState(id,this);
return this.dom.parentNode.removeChild(this.dom);
};
工厂进行对象实例化
var UploadFactory=(function(){
var createdFlyWeightObjs={};
return {
create:function(uploadType){
if(createdFlyWeightObjs[uploadType]){
return createdFlyWeightObjs[uploadType];
}
return createdFlyWeightObjs[uploadType]=new Upload(uploadType);
}
}
})();
管理器封装外部状态
完善前面提到的uploadManager对象,它负责向UploadFactory提交创建对象的请求
并用uploadDatabase对象保存所有的upload对象的外部状态
var uploadManager=(function(){
var uploadDatabase={};
return {
add:function(id,uploadType,fileName,fileSize){
var flyWeightObj=UploadFactory.create(uploadType);
var dom=document.createElement('div');
dom.innerHTML=
'<span>文件名称:'+this.fileName+',文件大小:'+this.fileSize+'</span>'
+'<button class="delFile">删除</button>';
dom.querySelector('.delFile').onclick=function(){
flyWeightObj.delFile(id);
};
document.body.appendChild(dom);
uploadDatabase[id]={
fileName:fileName,
fileSize:fileSize,
dom:dom
};
return flyWeightObj;
},
setExternalState:function(id,flyWeightObj){
var uploadData=uploadDatabase[id];
for(var i in uploadData){
flyWeightObj[i]=uploadData[i];
}
}
}
})();
触发上传动作的startUpload函数
var id=0;
window.startUpload=function(uploadType,files){
for(var i=0,file;file=files[i++];){
var uploadObj=uploadManager.add(++id,uploadType,file.fileName,file.fileSize);
}
};
接下来分别创建3个插件上传对象和3个flash上传对象
startUpload('plugin',[
{
fileName:'1.txt',
fileSize:1000
},
{
fileName:'2.html',
fileSize:3000
},
{
fileName:'3.txt',
fileSize:5000
}
]);
startUpload('flash',[
{
fileName:'4.txt',
fileSize:1000
},
{
fileName:'5.html',
fileSize:3000
},
{
fileName:'6.txt',
fileSize:5000
}
]);
这里一共有6个需要上传的文件,一共创建了2个upload对象
一个是插件类型的upload对象,一个是flash类型的upload对象
1.3 对象池技术
对象池也是一种共享相关的技术,对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接new,而是转从对象池获取
如果此时对象池里没有空闲对象,则创建一个新的对象
通用对象池实现
var objectPoolFactory=function(createObjFn){
var objectPool=[];
return {
create:function(){
var obj=objectPool.length === 0 ?
createObjFn.apply(this,arguments):objectPool.shift();
return obj;
},
recover:function(obj){
objectPool.push(obj);
}
}
};
利用objectPoolFactory创建一个装载iframe的对象池
var iframeFactory=objectPoolFactory(function(){
var iframe=document.createElement('iframe');
document.body.appendChild(iframe);
iframe.onload=function(){
iframe.onload=null;
iframeFactory.recover(iframe);//加载完成后,回收节点
}
return iframe;
});
setTimeout(function(){
var iframe=iframeFactory.create();
iframe.src='http://www.qq.com';
},1000);
这里每隔1秒通过工厂方法创建一个iframe,但是采用上述对象池,始终只会生产一个iframe对象
《JavaScript设计模式与开发实践》读书笔记之享元模式的更多相关文章
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)
说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(下)
上部分主要介绍高阶函数的常见形式,本部分将着重介绍高阶函数的高级应用. 1.currying currying指的是函数柯里化,又称部分求值.一个currying的函数会先接受一些参数,但不立即求值, ...
- Javascript设计模式与开发实践读书笔记(1-3章)
第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用 多态最根本好处在于,你不必询问对象“你是什么类型”而后根据得到的答案调用对象的某个行为--你只管调用行为就好,剩下的一切 ...
- javascript设计模式与开发实践阅读笔记(8)——观察者模式
发布-订阅模式,也叫观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 在JavaScript开发中,我们一般用事件模型来替代传统的观察者模式. ...
- javascript设计模式与开发实践阅读笔记(7)——迭代器模式
迭代器模式:指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...
- javascript设计模式与开发实践阅读笔记(6)——代理模式
代理模式:是为一个对象提供一个代用品或占位符,以便控制对它的访问. 代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对 ...
- javascript设计模式与开发实践阅读笔记(4)——单例模式
定义 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 具体来说,就是保证有些对象有且只有一个,比如线程池.全局缓存.浏览器中的window 对象等.在js中单例模式用途很广,比如登录 ...
- 《JavaScript设计模式与开发实践》笔记第八章 发布-订阅模式
第八章 发布-订阅模式 发布-订阅模式描述 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于 ...
- 《JavaScript设计模式与开发实践》笔记第一章
第一章 面向对象的JavaScript 动态类型语言和鸭子类型 编程语言按照数据类型大体可以分为两类:静态类型语言.动态类型语言. 静态类型语言:在编译时便已确定变量的类型. 优点: 在编译时就能发现 ...
随机推荐
- mfc控件与其对应的对象的关联方法
对话框的控件与其对应类的对象相关联:(两种方法) (1) 通过CWnd::DoDataExchange函数进行关联: 用VC++6.0的MFC ClassWizard中的Member Var ...
- uva 1374 快速幂计算
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #i ...
- android在其他线程中访问UI线程的方法
1.Activity.runOnUiThread( Runnable ) 2.View.post( Runnable ) 3.View.postDelayed( Runnable, long ) 4. ...
- Swift Swift语言Storyboard教程:第二部
本文由CocoaChina翻译小组@TurtleFromMars翻译自raywenderlich,原文:Storyboards Tutorial in Swift: Part 2 更新记录:该Stor ...
- Java Design Demo -简单的队列-异步多任务队列(java android)
简单的单线程队列 -- 工作的时候遇到劣质打印机.给打印机发消息,打印机就会打印,如果在打印机还在打印的时候,就 再发消息打印,就会出现消息丢失.所以需要给上一个任务一些处理的间隔时间. 单线程的消息 ...
- 多个haproxy 之间跳转
C:\>ping wechatTest.winfae.com 正在 Ping wechatTest.winfae.com [120.55.118.6] 具有 32 字节的数据: 来自 120.5 ...
- eclipse Maven plugin 配置
1. eclipse -> help -> marketpalce -> search 在输入框中输入Maven,回车. 在搜索结果列表中往下拉几个安装 Maven Integrat ...
- WinRarHelper帮助类
WinRarHelper帮助类 关于本文档的说明 本文档使用WinRAR方式来进行简单的压缩和解压动作,纯干货,实际项目这种压缩方式用的少一点,一般我会使用第三方的压缩dll来实现,就如同我上一个压缩 ...
- Github干货系列:C++资源集合-
Awesome CPP,这又是一个 Awesome XXX 系列的资源整理,由 fffaraz 发起和维护.内容包括:标准库.Web应用框架.人工智能.数据库.图片处理.机器学习.日志.代码分析等. ...
- Win8下在Vmware11中安装使用苹果系统OS X 10.10
原文:Win8下在Vmware11中安装使用苹果系统OS X 10.10 近来因为需要做 iOS 的项目,所以需要多花一些时间看看敲敲代码.因为自己手头上并没有 Mac(过年为了闲的时候能玩玩游戏 ...