保證一個類僅有一個例項,並且提供一個訪問它的全域性訪問點
單例模式的思路是:一個類能返回一個物件的引用(並且永遠是同一個)和一個獲得該例項的方法(靜態方法,通常使用 getInstance 名稱)。那麼當我們呼叫這個方法時,如果類持有的引用不為空就返回該引用,否者就建立該類的例項,並且將例項引用賦值給該類保持的那個引用再返回。同時將該類的建構函式定義為私有方法,避免其他函式使用該建構函式來例項化物件,只通過該類的靜態方法來得到該類的唯一例項。
應用場景
日常開發中,經常製作彈窗的時候我們需要一個半透明的遮罩層,為了減少不必要的dom操作,我們正確的思路應該是,判斷有沒有生成過這個 model
div 如果已經生成了就不必再次生成。
實現步驟
步驟1 寫一個生成 model div的方法
<style>
.modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .5;
background: #000;
z-index: 99;
}
</style>
<script>
function createModal () {
const div = document.createElement(`div`);
div.className = `modal`;
document.body.appendChild(div);
}
createModal()
createModal() // 呼叫兩次 將會產生兩個模態框
</script>
複製程式碼
呼叫兩次 createModal
方法將會產生在body上追加兩個div 很顯然不是我們需要的結果,我們需要增加一個變數判斷是否已經呼叫過
根據單例模式的定義來實現
- 保證一個類僅有一個例項
new createModal()
- 並且提供一個訪問它的全域性訪問點
createModal.getInstance
方法訪問
function createModal () {
const div = document.createElement(`div`);
div.className = `modal`;
document.body.appendChild(div);
}
createModal.getInstance = function () {
if (this.instace) {
return this.instace;
} else {
this.instace = new createModal();
return this.instace;
}
};
const a = createModal.getInstance()
const b = createModal.getInstance() // 呼叫兩次 例項一次
console.log(a === b) // true
複製程式碼
此段程式碼就根據單例模式的定義來用js實現了一個單例模式,呼叫多次也只會例項一個 createModal ,生成一個模態框
惰性單例
由於js的特性,可用閉包的形式保護一個私有變數,讓他來作為判斷值,並且惰性函式代表:在需要的時候才建立物件例項,而非在頁面載入時就建立
const createModal = (function(){
let div;
return function(){
if(!div){
div = document.createElement(`div`);
div.className = `modal`;
document.body.appendChild(div);
}
}
})();
createModal()
createModal() // 呼叫兩次 div 生成一次
複製程式碼
通過閉包,保護了 div 變數,在呼叫時候判斷
通用模式
通過上面程式碼我們發現如果需要新建另外一個div,只能複製程式碼,是否能想辦法把 return 裡生成div 的方法分離出來呢。
- 建立一個
getSingle
方法result
為判斷變數 - 建立一個
createModal
的方法為具體執行程式碼,並且返回一個bool值給getSingle
中的result
進行判斷
const getSingle = function (fn) {
let result;
return function () {
return result || (result = fn.apply(this, arguments));
}
};
const createModal = function () {
const div = document.createElement(`div`);
div.className = `modal`;
document.body.appendChild(div);
return div
}
const createSingleDiv = getSingle(createModal)
const a = createSingleDiv()
const b = createSingleDiv()
console.log(a === b) // true
複製程式碼
這樣就建立了一個 建立惰性單例的通用模式了
總結
單例模式在實際開發中應用很多,特別是在框架設計,合理利用可以提高效能。