享元(flyweight)模式是一种用于性能优化的模式,“fly”在这里是苍蝇的意思,意为蝇量级。享元模式的核心是运用共享技术来有效支持大量细粒度的对象。
享元模式是使用同一个对象处理大量同种业务的模式,其能够避免创建大量相似对象,减少内存使用。
享元模式将对象分为内部状态和外部状态。当两者组合成一个完整对象时使用。
- 内部状态存储于对象内部。
- 内部状态可以被一些对象共享。
- 内部状态独立于具体的场景,通常不会改变。
- 外部状态取决于具体的场景,并根据场景而变化,外部状态不能被共享。
使用享元模式对列表进行业务处理
//元对象
var Upload = function( uploadType ){
this.uploadType = uploadType; //内部状态
};
Upload.prototype.delFile = function( id ){
uploadManager.setExternalState( id, this ); //将uploadManager管理的外部状态绑定于元对象
if( this.fileSize < 3000 ){
//根据uploadType进行业务处理
//....
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 uploadManager = (function(){
var uploadDatabase = {}, //存储外部状态
return {
add: function( id, uploadType, fileName, fileSize ){
var flyWeightObj = UploadFactory.create( uploadType );
var dom = document.createElement('div');
dom.innerHTML = '<span>文件名称:' + fileName + ', 文件大小:' + 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 ];
}
}
}
})();
//上传的动作
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 );
}
};
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
}
]);
对象池技术与享元模式类似,但对象池没有主动分离内部状态和外部状态。以下为对象池代码:
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 );
}
}
};
//对象池的使用
var iframeFactory = objectPoolFactory( function(){
var iframe = document.createElement('iframe');
document.body.appendChild( iframe );
iframe.onload = function(){
iframe.onload = null; //防止iframe重复加载的bug
iframeFactory.recover( iframe ); //iframe加载完成之后回收节点
}
return iframe;
});
var iframe1 = iframeFactory.create();
iframe1.src = 'http://baidu.com';
var iframe2 = iframeFactory.create();
iframe2.src = 'http://QQ.com';
setTimeout(function(){
var iframe3 = iframeFactory.create();
iframe3.src = 'http://163.com';
},3000 );
网友评论