學(xué)習(xí)JavaScript設(shè)計(jì)模式之享元模式
一、定義
享元(flyweight)模式是一種用于性能優(yōu)化的模式,核心是運(yùn)用共享技術(shù)來有效支持大量細(xì)刻度的對(duì)象。
在JavaScript中,瀏覽器特別是移動(dòng)端的瀏覽器分配的內(nèi)存并不算多,如何節(jié)省內(nèi)存就成了一個(gè)非常有意義的事情。
享元模式是一種用時(shí)間換空間的優(yōu)化模式
- 內(nèi)衣工廠有100種男士內(nèi)衣、100中女士內(nèi)衣,要求給每種內(nèi)衣拍照。如果不使用享元模式則需要200個(gè)塑料模特;使用享元模式,只需要男女各1個(gè)模特。
二、什么場景下使用享元模式?
(1)程序中使用大量的相似對(duì)象,造成很大的內(nèi)存開銷
(2)對(duì)象的大多數(shù)狀態(tài)都可以變?yōu)橥獠繝顟B(tài),剝離外部狀態(tài)之后,可以用相對(duì)較少的共享對(duì)象取代大量對(duì)象
三、如何應(yīng)用享元模式?
第一種是應(yīng)用在數(shù)據(jù)層上,主要是應(yīng)用在內(nèi)存里大量相似的對(duì)象上;
第二種是應(yīng)用在DOM層上,享元可以用在中央事件管理器上用來避免給父容器里的每個(gè)子元素都附加事件句柄。
享元模式要求將對(duì)象的屬性分為內(nèi)部狀態(tài)和外部狀態(tài)。
內(nèi)部狀態(tài)獨(dú)立于具體的場景,通常不會(huì)改變,可以被一些對(duì)象共享;
外部狀態(tài)取決于具體的場景,并根據(jù)場景而變化,外部狀態(tài)不能被共享。
享元模式中常出現(xiàn)工廠模式,F(xiàn)lyweight的內(nèi)部狀態(tài)是用來共享的,F(xiàn)lyweight factory負(fù)責(zé)維護(hù)一個(gè)Flyweight pool(模式池)來存放內(nèi)部狀態(tài)的對(duì)象。
缺點(diǎn):對(duì)象數(shù)量少的情況,可能會(huì)增大系統(tǒng)的開銷,實(shí)現(xiàn)的復(fù)雜度較大!
四、示例:文件上傳
var Upload = function(uploadType) {
this.uploadType = uploadType;
}
/* 刪除文件(內(nèi)部狀態(tài)) */
Upload.prototype.delFile = function(id) {
uploadManger.setExternalState(id, this); // 把當(dāng)前id對(duì)應(yīng)的外部狀態(tài)都組裝到共享對(duì)象中
// 大于3000k提示
if(this.fileSize < 3000) {
return this.dom.parentNode.removeChild(this.dom);
}
if(window.confirm("確定要?jiǎng)h除文件嗎?" + this.fileName)) {
return this.dom.parentNode.removeChild(this.dom);
}
}
/** 工廠對(duì)象實(shí)例化
* 如果某種內(nèi)部狀態(tài)的共享對(duì)象已經(jīng)被創(chuàng)建過,那么直接返回這個(gè)對(duì)象
* 否則,創(chuàng)建一個(gè)新的對(duì)象
*/
var UploadFactory = (function() {
var createdFlyWeightObjs = {};
return {
create: function(uploadType) {
if(createdFlyWeightObjs[uploadType]) {
return createdFlyWeightObjs[uploadType];
}
return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
}
};
})();
/* 管理器封裝外部狀態(tài) */
var uploadManger = (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];
}
}
};
})();
/*觸發(fā)上傳動(dòng)作*/
var id = 0;
window.startUpload = function(uploadType, files) {
for(var i=0,file; file = files[i++];) {
var uploadObj = uploadManger.add(++id, uploadType, 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',
fileSize: 1000
},{
fileName: '5.txt',
fileSize: 3000
},{
fileName: '6.txt',
fileSize: 5000
}
]);
五、補(bǔ)充
(1)直接改變形參Demo
function f1() {
var obj = {a: 1};
f2(obj);
console.log(obj); // {a: 1, b: 2}
}
function f2(obj) {
obj.b = 2;
}
f1();
(2)對(duì)象池,也是一種性能優(yōu)化方案,其跟享元模式有一些相似之處,但沒有分離內(nèi)部狀態(tài)和外部狀態(tài)的過程。
var objectPoolFactory = function(createObjFn) {
var objectPool = [];
return {
create: function() {
var obj = objectPool.lenght === 0 ? createObjFn.apply(this, arguments) : objectPool.shift();
return obj;
},
recover: function() {
objectPool.push(obj);
}
};
}
希望本文所述對(duì)大家學(xué)習(xí)javascript程序設(shè)計(jì)有所幫助。
- javascript設(shè)計(jì)模式之享元模式
- javascript設(shè)計(jì)模式 – 享元模式原理與用法實(shí)例分析
- javascript 設(shè)計(jì)模式之享元模式原理與應(yīng)用詳解
- JavaScript享元模式原理與用法實(shí)例詳解
- JavaScript設(shè)計(jì)模式之享元模式實(shí)例詳解
- JavaScript使用享元模式實(shí)現(xiàn)文件上傳優(yōu)化操作示例
- js設(shè)計(jì)模式之結(jié)構(gòu)型享元模式詳解
- 輕松掌握J(rèn)avaScript享元模式
- JS實(shí)現(xiàn)簡單的圖書館享元模式實(shí)例
- JavaScript設(shè)計(jì)模式之性能優(yōu)化模式享元模式
相關(guān)文章
微信小程序?qū)崿F(xiàn)圖片拖拽調(diào)換位置效果(開箱即用)
本篇文章給大家介紹如何在微信小程序中實(shí)現(xiàn)圖片的拖拽排序和刪除功能,通過創(chuàng)建自定義組件并使用示例代碼,代碼簡單易懂,感興趣的朋友跟隨小編一起看看吧2024-12-12
使用Promise封裝小程序wx.request的實(shí)現(xiàn)方法
這篇文章主要介紹了使用Promise封裝小程序wx.request的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
用console.table()調(diào)試javascript
昨天我了解到Chrome調(diào)試工具一個(gè)小巧的調(diào)試方法,在WDCC期間, Marcus Ross(@zahlenhelfer) 介紹了,chrome調(diào)試工具各種調(diào)試方法,這個(gè)只是其中一種,現(xiàn)在我來給大家秀下。2014-09-09
JS 實(shí)現(xiàn)導(dǎo)航欄懸停效果(續(xù))
上次導(dǎo)航欄懸停的那個(gè)頁面在IE上運(yùn)行的時(shí)候,會(huì)出導(dǎo)航欄不停的抖動(dòng)問題,在本文已有完美的解決方法,將導(dǎo)航欄的定位方式由原來的absolute改為fixed即可2013-09-09
用javascript實(shí)現(xiàn)的電信鐵通(網(wǎng)通)自動(dòng)跳轉(zhuǎn)源代碼
用javascript實(shí)現(xiàn)的電信鐵通(網(wǎng)通)自動(dòng)跳轉(zhuǎn)源代碼...2007-11-11
JavaScript實(shí)現(xiàn)復(fù)選框全選和取消全選
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)復(fù)選框全選和取消全選,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
js中<script> 標(biāo)簽中type值及其含義
在 HTML 中的 script 標(biāo)簽中,type 屬性用于指定腳本的 MIME 類型,也即告訴瀏覽器該如何解釋和處理腳本的內(nèi)容,這篇文章主要介紹了js中<script> 標(biāo)簽中type值及其含義,需要的朋友可以參考下2024-12-12

