JavaScript的單例模式沒有那麼簡單

想必大家都知道單例模式就是不管調用多少次new命令,始終只能創建一個實例對象。

寫個方法來看看javaScript的單例長什麼樣。

下面這個例子是負責在頁面中創建唯一的div節點。代碼如下

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
})()

是不是跟你寫的不太一樣,是不是覺得這樣寫更好?

雖然這已經是優化過的js單例代碼,但是他依然有缺點:

爲了把instance封裝起來,我們使用了自執行的匿名函數和閉包,並且讓這個匿名函數返回真正的Singleton構造方法

這增加了一些程序的複雜度,閱讀起來比較費勁。

觀察這個Singleton構造函數

 var CreateDiv = function(html){
      if(instance){
        return instance;
      }
      this.html = html;
      this.init();
      return instance = this;
  }

它實際負責了兩件事情1:創建對象和執行初始化init方法。2:保證只有一個對象。這與‘單一指責原則’違背

用代理模式實現單一職責的單例

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);
}

接下來引入代理類proxySingletonCreateDiv

var ProxySingletonCreateDiv = (function(){
  var instance;
  return function(html){
     if(!instance){
       instance = new CreateDiv(html)
     }
     return instance
  }
})()

通過引入代理類的方式實現了單一職責的單例模式。噢耶~~~

CreateDiv只負責創建對象和初始化。ProxySingletonCreateDiv負責保證只有一個對象。

// 創建一個dog單例 來鞏固一下
var Dog = function(name){
   this.name = name;
   this.init();
}
Dog.prototype.init=function(){
  console.log('I am dog, my name is '+this.name)
}
var ProxySingletonCreateDog = (function(name){
  var instance
  return function (name){
    if(!instance){
       instance = new Dog(name)
    }
    return instance
  }
})()

但是但是!上面的例子更多的接近傳統的面向對象的語言實現,而javascript是一門無類語言,生搬單例模式並無意義  嗚嗚嗚。

在javascript中創建單例模式非常的簡單,既然我們只需要一個唯一的對象,爲什麼要爲它創建一個類呢???這無異於穿衣服洗澡,傳統的單例模式實現在JavaScript中並不適用!!

單例模式的核心1 保證只有一個實例2提供全局訪問方法

全局變量不是單例模式,但是我們經常把全局變量當成單例來使用。

全局變量會造成命名空間污染,內存溢出等問題,所以儘量少使用全局變量。

我們可以使用閉包來實現單例

var User = (function(){
  var _name = 'stupidcc';
  var _age = 18;
  return {
     getName: function(){
        return _name 
     },
     getAge: function () {
        return _age
     },
     setAge: function(age){
        _age = age
     }
  }
})()

惰性單例

惰性是單例模式的重點,重點哦。

這種技術在開發過程中非常有用,有用程度可能超出了你的想象。

例如我們需要在頁面中創建一個iframe,使用單例

// 代理
var getSingleton = function(fn){
   var result;
   return function (fn) {
     return result || (result = fn.apply(this,arguments))
   }
}
var initIframe = function () {
   var iframe = document.createElement('iframe')
   document.body.appendChild(iframe)
   return iframe
}
var CreateSingletonIframe = getSingleton(initIframe)
document.getElementById('button').onclick=function(){
   var iframeObj = CreateSingletonIframe()
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章