享元模式
享元模式是一種用於性能優化的模式,享元模式的核心就是運用共享技術來有效支持大量細粒度的對象。享元模式要求將對象的屬性劃分爲內部狀態和外部狀態。享元模式的目標就是儘量減少共享對象的數量。
怎樣劃分內部狀態和外部狀態?
- 內部狀態存儲於對象內部
- 內部狀態可以被一些對象共享
- 內部狀態獨立於具體場景,通常不會改變
- 外部狀態取決於具體的場景,並根據場景變化,外部狀態不能被共享
這樣一來,我們便可以把所有內部狀態都相同的對象都指定爲同一個共享對象。而外部狀態可以從對象身上剝離,並存儲在外部。
比如,當我們需要模特分別爲500種男士衣服和500種女士衣服打廣告,在最壞的情況下我們可以用500名男/女模特,分別穿上500種不同的衣服,但是這樣顯然是不好的;因爲我們可以只使用1名男/女模特依次穿上500種不同的衣服。在這裏性別就可以劃分爲內部狀態,不同的衣服就可以劃分爲外部狀態。
例子
<script>
let id = 0
window.startUpload = function (uploadType, files) {
files.forEach(file => {
let uploadObj = new Upload(uploadType, file.fileName, file.fileSize)
uploadObj.init(id++)
});
}
let Upload = function (type, name, size) {
this.uploadType = type
this.fileName = name
this.fileSize = size
this.dom = null
}
Upload.prototype.init = function (id) {
let that = this
this.id = id
this.dom = document.createElement('div')
this.dom.innerHTML =
`
<span>文件名:${this.fileName},文件大小:${this.fileSize}
<button class="delFile">刪除</button>
`
this.dom.querySelector('.delFile').onclick = function () {
that.delFile()
}
document.body.appendChild(this.dom)
}
Upload.prototype.delFile = function () {
if (this.fileSize < 3000) {
return this.dom.parentNode.removeChild(this.dom)
}
if (window.confirm(`are you sure delete file of ${this.fileName}`)) {
return this.dom.parentNode.removeChild(this.dom)
}
}
startUpload('plugin', [{
fileName: 1,
fileSize: 1000,
},{
fileName: 2,
fileSize: 2000,
},{
fileName: 3,
fileSize: 3000,
},{
fileName: 4,
fileSize: 4000,
}])
</script>
在上面的這個例子中我們發現我們有多少個文件就會創建多少個對象,這樣的情況下如果需要創建大量的文件瀏覽器就會吃不消。所以我們分析代碼,發現uploadType
是內部狀態,因爲當瀏覽器確定上傳方式也就確定了,fileName;fileSize
是外部狀態因爲不同的文件的名稱和大小不同。所以我們將uploadType
作爲內部對象從構造函數中剝離出來。
對象池
對象池維護一個裝載空閒對象的池子,如果需要對象的時候,不是直接new,而是轉而從對象池中獲取,如果對象池沒有空閒的對象,則創建一個新的對象,當獲取出的對象完成它的職責之後,在進入池子等待下次被獲取。