簡單點來講,單例模式就是確保某個類只有一個實例,而且最好只被建立過一次。對計算機來講,像打印機,線程池都是經典的單例模式。對於JavaScript所處的前端環境來講,像登陸懸浮框,在整個頁面中只會有一個,不管用戶點擊多少次,只會被建立一次。前端
單例模式很是好理解,無非是辦公室有個打印機,你們一塊兒公用,不必再每一個人單獨買一個了。因此按照這樣的理解,先寫出前端建立懸浮登陸框的前端代碼:設計模式
var createLoginDialog = function(){ var div = document.createElement('div'); div.innerHTML='登陸懸浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); return div; } document.getElementById('loginBtn').onclick = function(){ var loginDiv = createLoginDialog(); }
這應該是咱們平時寫出的「通常」實現單例代碼,看起來單例是實現了。但有很大問題,就是每次建立都會新生成一個div,性能損耗不談,自己也不是真正實現了單例模式。
單例模式的關鍵實現一是要在須要建立的時候纔開始建立,即惰性建立,第二就是隻被建立一次,再次使用的時候,不須要重複建立。在其餘語言實現中,須要藉助靜態方法或者其餘手段來使代碼駐留內存,達到這一目的。JavaScript卻不提供,但內存駐留卻使咱們想到了閉包。
因此再次修改代碼,建立一個閉包來實現。閉包
var createLoginDialog = (function(){ var div; return function(){ if(!div){ div = document.createElement('div'); div.innerHTML='登陸懸浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); }else{ div.style.display='block'; } return div; } })(); document.getElementById('loginBtn').onclick = function(){ var loginDiv = createLoginDialog(); }
實際上,對於js單例模式最核心的邏輯就是app
var obj; if(!obj){ obj = XXX; }
而對於以上最後寫出的建立代碼,也不盡完美,由於它違反了設計模式中的單一職原則。即建立對象和管理單例的邏輯都放在一個類的內部。
據此,咱們能夠剝離出建立單例模式的方法性能
var getSingleton = function(fn){ var result; return function(){ return result || (result = fn.apply(this,arguments)); } }
最終在這個方法下實現代碼:this
var createLoginDialog = function(){ var div = document.createElement('div'); div.innerHTML='登陸懸浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); return div; } var getSingleton = function(fn){ var result; return function(){ return result || (result = fn.apply(this,arguments)); } } var createSingletonLogin = getSingleton(createLoginDialog); document.getElementById('loginBtn').onclick = function(){ var loginDiv = createSingletonLogin(); loginDiv.style.display = 'block'; }