设计模式-javascript实现【享元模式】
定义:享元模式是一种用于性能优化的模式,其核心是运用共享技术来有效支持大量细粒度的对象。享元模式
要求将对象的属性划分为内部状态与外部状态(通常指属性),其目标是尽量减少共享对象的数量。
内部状态和外部状态:
- 内部状态存储于对象内部
- 内部状态可以被一些对象共享
- 内部状态独立于具体的场景,通常不会改变
- 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享
我们便可以把所有内部状态相同的对象都指定为同一个共享对象。而外部状态可以从对象身上剥离出来,并储存
在外部。
1. 享元模式的实现
// 共享类
class Upload {
constructor(uploadType){
this.uploadType = uploadType;
}
delFile(){
// 通过外部管理器设置 对象的fileSize
uploadManager.setExternalState(id, this);
if(this.fileSize < 3000){
return this.dom.parentNode.removeChild(this.dom);
}
if(window.confirm('确定要删除该文件吗?’ + this.fileName)){
return this.dom.parentNode.removeChild(this.dom);
}
}
}
// 工厂函数创建并缓存对象
const uploadFactory = (function(){
const createdFlyWeightObjs = {};
return {
create: function(uploadType){
if(createdFlyWeightObjs[uploadType]){
return createdFlyWeightObjs[uploadType];
}
return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
}
};
})();
const uploadManager = (function(){
const uploadDatabase = {};
return {
add: function(id, uploadType, fileName, fileSize){
const flyWeightObj = UploadFactory.create(uploadType);
const dom = document.createElement('div');
dom.innerHTML = '<span>文件名称:' + fileName + ', 文件大小: ' + fileSize + '</span>' +
'<button class="delFile">删除</button>';
dom.querySelector('.delFile').onclick = function(){
flyWeightObj.delFile(id);
};
dom.body.appendChild(dom);
uploadDatabase[id] = { fileName, fileSize, dom };
return flyWeightObj;
},
setExternalState: function(id, flyWeightObj){
const uploadData = uploadDatabase[id];
for(let key in uploadData){
flyWeightObj[key] = uploadData[key];
}
}
};
});
const startUpload = function(uploadType, files){
let id = 0;
for(let i = 0; i < files.length; i++){
uploadManager.add(++id, uploadType, files[i].fileName, files[i].fileSize);
}
}
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
}
]);
享元模式是一种很好的性能优化方案,但它也会带来一些复杂性的问题,享元模式带来的好处很大程度上取决于
如何使用以及何时使用,一般来说,以下情况发生时便可以使用享元模式。
- 一个程序中使用了大量的相似对象
- 由于使用了大量对象,造成很大的内存开销
- 对象的大多数状态都可以变为外部状态
- 剥离出对象的外部状态之后,可以用相对较少的共享对象取代大量对象
2. 对象池
对象池维护一个装载空闲对象的池子,如果需要对象的时候,不是直接new,而是转从对象池里获取。如果对象
池里没有空闲对象,则创建一个新的对象,当获取出的对象完成它的职责之后,再进入池子等待被下次获取。
对象池是另外一种性能优化方案,它跟享元模式有一些相似之处,但没有分离内部状态和外部状态这个过程。
function objectFollFactory = function(createObjFn){
let objectPool = [];
return {
create: function(){
return objectPool.length === 0 ? createObjFn.apply(this, arguments) : objectPool.shift();
},
recover: function(obj){
objectPool.push(obj);
}
};
}
const iframeFactory = objectPoolFactory(function(){
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.onload = function(){
iframe.onload = null;
iframeFactory.recover(iframe);
}
});
const iframe1 = iframeFactory.create();
iframe1.src = 'http://badiu.com';
const iframe2 = iframeFactory.create();
iframe2.src = 'http://qq.com';