享元(flyweight)模式是一種用于性能優(yōu)化的模式,“fly”在這里是蒼蠅的意思,意為蠅量級。享元模式的核心是運用共享技術(shù)來有效支持大量細粒度的對象。
享元模式是使用同一個對象處理大量同種業(yè)務(wù)的模式,其能夠避免創(chuàng)建大量相似對象,減少內(nèi)存使用。
享元模式將對象分為內(nèi)部狀態(tài)和外部狀態(tài)。當(dāng)兩者組合成一個完整對象時使用。
- 內(nèi)部狀態(tài)存儲于對象內(nèi)部。
- 內(nèi)部狀態(tài)可以被一些對象共享。
- 內(nèi)部狀態(tài)獨立于具體的場景,通常不會改變。
- 外部狀態(tài)取決于具體的場景,并根據(jù)場景而變化,外部狀態(tài)不能被共享。
使用享元模式對列表進行業(yè)務(wù)處理
//元對象
var Upload = function( uploadType ){
this.uploadType = uploadType; //內(nèi)部狀態(tài)
};
Upload.prototype.delFile = function( id ){
uploadManager.setExternalState( id, this ); //將uploadManager管理的外部狀態(tài)綁定于元對象
if( this.fileSize < 3000 ){
//根據(jù)uploadType進行業(yè)務(wù)處理
//....
return this.dom.parentNode.removeChild( this.dom );
}
if( window.confirm('確定要刪除該文件嗎?' + this.fileName )){
return this.dom.parentNode.removeChild( this.dom );
}
};
//使用工廠進行實例化,相同內(nèi)部狀態(tài)只實例化一次
var UploadFactory = (function(){
var createdFlyWeightObjs = {};
return {
create: function( uploadType ){
if( createdFlyWeightObjs[ uploadType ] ){
return createdFlyWeightObjs[ uploadType ];
}
return createdFlyWeightObjs[ uploadType ] = new Upload( uploadType );
}
}
})();
//管理器封裝外部狀態(tài)
var uploadManager = (function(){
var uploadDatabase = {}, //存儲外部狀態(tài)
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
}
]);
對象池技術(shù)與享元模式類似,但對象池沒有主動分離內(nèi)部狀態(tài)和外部狀態(tài)。以下為對象池代碼:
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重復(fù)加載的bug
iframeFactory.recover( iframe ); //iframe加載完成之后回收節(jié)點
}
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 );