享元模式是一種用于性能優(yōu)化的模式,享元模式的核心是運用共享技術來有效支持大量細粒度的對象。
如果系統(tǒng)中創(chuàng)建了大量類似的對象而導致內存占用過高,享元模式就非常有用了。在JavaScript中,瀏覽器特別是移動端分配的內存并不算多,如何節(jié)省內存就成了一件非常有意義的事情。
為了讓我們能更好的理解享元模式,下面先說一個例子。
享元模式案例
假設有個網店,目前有50件男裝和50件女裝,為了推銷產品,需要找模特穿上衣服,進行拍攝圖片。在不適用享元模式的情況下,實現(xiàn)如下:
const Model = function (sex, wear) {
this.sex = sex
this.wear = wear
}
Model.prototype.takePhoto = function () {
console.log(`sex=${this.sex} wear=${this.wear}`)
}
for (let i = 1; i <= 50; i++) {
let maleModel = new Model('male', `wear${i}`)
maleModel.takePhoto()
let femaleModel = new Model('female', `wear${i}`)
femaleModel.takePhoto()
}
要得到一張照片,每次需要生成100個對象,如果將來有10000種衣服,那這個程序有可能因此而奔潰。
接下來我們來改造下上面的代碼:
const Model = function(sex) {
this.sex = sex
}
Model.prototype.takePhoto = function () {
console.log(`sex=${this.sex} wear=${this.wear}`)
}
const maleModel = new Model('male')
const femaleModel = new Model('female')
for (let i = 1; i <= 50; i++) {
maleModel.wear = `wear${i}`
maleModel.takePhoto()
femaleModel.wear = `wear${i}`
femaleModel.takePhoto()
}
可以看到,改性之后的代碼,只需要兩個對象便完成了同樣的功能。上面的代碼便是享元模式的雛形。
內部狀態(tài)與外部狀態(tài)
享元模式要求將對象屬性劃分為內部狀態(tài)和外部狀態(tài)。
享元模式的目標是盡量減少共享對象的數量。
關于如何劃分內部狀態(tài)和外部狀態(tài),下面是幾條大致的規(guī)則:
- 內部狀態(tài)存儲于對象內部
- 內部狀態(tài)可以被一些對象共享
- 內部狀態(tài)獨立與具體的場景,通常不會改變
- 外部狀態(tài)取決于具體的場景,并根據場景而變化,外部狀態(tài)不能被共享
這樣指定內部狀態(tài)相同的對象都指定為同一個共享的對象。而外部狀態(tài)可以從對象身上剝離出來,并存儲在外部。
享元模式的應用
跳轉頁面在前端開發(fā)過程中,是最常見的一種操作。在頁面跳轉的時候加上一些額外的操作,也是常見的。下面是使用享元模式實現(xiàn)的應用跳轉:
function setExternalState (...args) {
sessionStorage.setItem('state', 1)
alert(sessionStorage.getItem('state') + args[0])
}
function Page (urls) {
this.urls = {
baidu: 'https://www.baidu.com',
taobao: 'https://www.taobao.com',
jianshu: 'http://www.itdecent.cn',
...urls
}
}
Page.prototype.jumpUrl = function (key, fn, ...args) {
fn && fn.apply(null, args)
const url = this.urls[key]
location.href = url
}
window.onload = () => {
const page = new Page()
page.jumpUrl('baidu', setExternalState, 'haha')
}