学习JavaScript设计模式之享元模式

@H_3010@

一、定义


@H
301_0@享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象。
在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情。
享元模式是一种用时间换空间的优化模式

@H_301_0@

二、什么场景下使用享元模式?

@H_301_0@(1)程序中使用大量的相似对象,造成很大的内存开销 (2)对象的大多数状态都可以变为外部状态,剥离外部状态之后,可以用相对较少的共享对象取代大量对象

@H_301_0@

三、如何应用享元模式?

@H_301_0@第一种是应用在数据层上,主要是应用在内存里大量相似的对象上; 第二种是应用在DOM层上,享元可以用在中央事件管理器上用来避免给父容器里的每个子元素都附加事件句柄。

@H_301_0@享元模式要求将对象的属性分为

内部状态

外部状态

。 内部状态独立于具体的场景,通常不会改变,可以被一些对象共享; 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。

@H_301_0@享元模式中常出现工厂模式,Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个Flyweight pool(模式池)来存放内部状态的对象。

@H_301_0@缺点:对象数量少的情况,可能会增大系统的开销,实现的复杂度较大!

@H_301_0@

四、示例:文件上传

/ 删除文件(内部状态) /
Upload.prototype.delFile = function(id) {
uploadManger.setExternalState(id,this); // 把当前id对应的外部状态都组装到共享对象中
// 大于3000k提示
if(this.fileSize < 3000) {
return this.dom.parentNode.removeChild(this.dom);
}
if(window.confirm("确定要删除文件吗?" + this.fileName)) {
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);
    }
    };
    })();

/ 管理器封装外部状态 /
var uploadManger = (function() {
var uploadDatabase = {};

return {
add: function(id,uploadType,fileName,fileSize) {
var flyWeightObj = UploadFactory.create(uploadType);
var dom = document.createElement('div');
dom.innerHTML = "文件名称:" + fileName + ",文件大小:" + fileSize +""

  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];
  }
}

};
})();

/触发上传动作/
var id = 0;
window.startUpload = function(uploadType,files) {
for(var i=0,file; file = files[i++];) {
var uploadObj = uploadManger.add(++id,file.fileName,file.fileSize);
}
};

/ 测试 /
startUpload("plugin",[
{
fileName: '1.txt',fileSize: 1000
},{
fileName: '2.txt',fileSize: 3000
},{
fileName: '3.txt',fileSize: 5000
}
]);
startUpload("flash",[
{
fileName: '4.txt',{
fileName: '5.txt',{
fileName: '6.txt',fileSize: 5000
}
]);

@H_301_0@

五、补充

@H_301_0@(1)直接改变形参Demo

@H_301_0@(2)对象池,也是一种性能优化方案,其跟享元模式有一些相似之处,但没有分离内部状态和外部状态的过程。

@H_301_0@希望本文所述对大家学习javascript程序设计有所帮助。

相关文章

事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数...
js小数运算会出现精度问题 js number类型 JS 数字类型只有number类型,number类型相当于其他强类型语言...
什么是跨域 跨域 : 广义的跨域包含一下内容 : 1.资源跳转(链接跳转,重定向跳转,表单提交) 2.资源...
@ &quot;TOC&quot; 常见对base64的认知(不完全正确) 首先对base64常见的认知,也是须知的必须有...
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : 的缩写,说都能直接说出来 :模型, :视图, :视图模...
首先我们需要一个html代码的框架如下: 我们的目的是实现ul中的内容进行横向的一点一点滚动。ul中的内容...