定義:單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。html
單例模式是一種經常使用的模式,有一些對象咱們每每只須要一個,好比線程池、全局緩存、瀏覽器中的window對象等。當咱們建立的對象只會被建立一次時,這個時候就適合用單例模式來建立,由於當咱們點擊登陸按鈕的時候,頁面會出現一個懸浮窗,而這個懸浮窗是惟一的,不管單擊多少次登陸按鈕,這個只會被建立一次。瀏覽器
實現單例模式緩存
實現一個標準的單例模式,用一個變量來標誌當前是否已經爲某個類建立過對象,若是是,則在下一次獲取該類的實例時,直接返回以前建立的對象。代碼以下: var Singleton = function( name ){ this.name = name; this.instance = null; }; Singleton.prototype.getName = function(){ alert( this.name ); }; Singleton.getIstance = function( name ){ if( !instance ){ this.instance = new Singleton( name ); } return this.instance; }; var a = Singleton.getInstance( 'tom' ); var b = Singleton.getInstance( 'sun' ); alert( a===b ); //true
咱們經過Singleton.getInstance來獲取Singleton類的惟一對象,簡單,但有一個問題,就是增長了這個類的「不透明性」,Singleton類的使用者必須知道這是一個單例類,跟以往經過new XXX的方式來獲取對象不一樣,這裏偏要使用Singleton.getInstance來獲取對象。app
透明的單例模式
實現一個「透明」的單例類,能夠是用戶從這個類中建立對象的時候,能夠像使用其餘普通函數同樣。函數
var createDiv = ( function(){ var instance; var createDiv = function( html ){ if( instance ){ return instance; } this.html = html; this.init(); return instance = this; }; createDiv.prototype.init = function(){ var div = document.createElement( 'div' ); div.innerHTML = this.html; document.body.appendChild( div ); } return createDiv; })(); var a = new createDiv('tom'); var b = new createDiv('sun'); alert( a === b ); //true
createDiv的構造函數實際上負責了兩件事情。第一是建立對象和執行初始化init方法,第二個是保證只有一個對象。有一個缺點,假如咱們某天須要利用這個類,在頁面中建立千千萬萬個div,即要這個類從單例類變成一個普通的可產生多個實例的類,那咱們就要改寫createDiv構造函數,把控制建立惟一對象的那一段去掉,這樣會給咱們帶來沒必要要的麻煩。this
代理類實現單例模式
咱們如今經過代理類來解決透明單例模式提到的問題。
經過引入代理類的方式,把負責管理單例的邏輯移到了代理類proxySingDivCreateDiv中,這樣,createDiv就變成了一個普通類,它跟代理類組合起來能夠實現單例模式的效果。prototype
var createDiv = function( html ){ this.html = html; this.init(); }; createDiv.prototype.init = function(){ var div = document.createElement( 'div' ); div.innerHTML = this.html; document.body.appendChild( div ); }; var proxySingletonCreateDiv = (function(){ var instance; return function( html ){ if(!instance){ instance = new createDiv( html ); } return instance; } })(); var a = new proxySingletonCreateDiv( 'tom' ); var b = new proxySingletonCreateDiv( 'sun' ); alert( a === b ); //true