《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 动态类型语言和鸭子类型 编程语言按照数据类型大体可以分为两类:静态类型语言.动态类型语言. 静态类型语言:在编译时便已确定变量的类型. 优点: 在编译时就能发现 ...
随机推荐
- 采用管道处理HTTP请求
采用管道处理HTTP请求 之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET ...
- Cocos2dx中Plugin-X 在android下的整合
直接拉plugin-x中的jar包导入到Eclipse中就可以.用这么麻烦的工具干嘛.
- _00024 尼娜抹微笑伊拉克_云计算ClouderaManager以及CHD5.1.0群集部署安装文档V1.0
笔者博文:妳那伊抹微笑 itdog8 地址链接 : http://www.itdog8.com(个人链接) 博客地址:http://blog.csdn.net/u012185296 博文标题:_000 ...
- pig对null的处理(实际,对空文本处理为两种取值null或‘’)
pig对文本null的处理非常特殊.会处理成两种null,还会处理成''这样的空值. 比方,读name,age,sex日志信息.name取值处理,假设记录为".,,"这样,会将na ...
- 【ASP.NET Web API教程】6 格式化与模型绑定
原文:[ASP.NET Web API教程]6 格式化与模型绑定 6 Formats and Model Binding 6 格式化与模型绑定 本文引自:http://www.asp.net/web- ...
- 按 Eclipse 开发喜好重新布置 cocos2dx 目录层次
[tonyfield 2013.08.29 ] 1. Cocos2dx 库的改动 处于个人的固执,花一天时间重新布置了cocos2dx 2.1.4的目录层次,将android平台无关的代码全数裁剪, ...
- 每次调用fork()函数之后,父线程和创建出的子线程都是从fork()后开始执行
Linux下多少个"-"将被打印: 1 2 3 4 5 6 7 8 int main(void){ int i; for(i=0;i<4;i++){ fork() ...
- Successful Lisp - Cover
Successful Lisp - Cover Successful Lisp: How to Understand and Use Common Lisp
- [Android学习笔记]ShareSDK的使用
ShareSDK使用方便,集成简单,正式客户端开发人员的首选组件 集成步骤,使用说明见官方文档: http://wiki.sharesdk.cn/Android_快速集成指南 记录: 直接使用官方De ...
- Android在onInterceptTouchEvent与onTouchEvent
onInterceptTouchEvent: onInterceptTouchEvent是在ViewGroup里面定义的.Android中的layout布局类一般都是继承此类的.onIntercept ...