JS設計模式一:單例模式

單例模式

 
    單例模式也稱做爲單子模式,更多的也叫作單體模式。爲軟件設計中較爲簡單可是最爲經常使用的一種設計模式。
 
    下面是維基百科對單例模式的介紹:
    在應用單例模式時,生成單例的類必須保證只有一個實例的存在,不少時候整個系統只須要擁有一個全局對象,纔有利於協調系統總體的行爲。好比在整個系統的配置文件中,配置數據有一個單例對象進行統一讀取和修改,其餘對象須要配置數據的時候也統一經過該單例對象來獲取配置數據,這樣就能夠簡化複雜環境下的配置管理。

    單例模式的思路是:一個類能返回一個對象的引用(而且永遠是同一個)和一個得到該實例的方法(靜態方法,一般使用 getInstance 名稱)。那麼當咱們調用這個方法時,若是類持有的引用不爲空就返回該引用,否者就建立該類的實例,而且將實例引用賦值給該類保持的那個引用再返回。同時將該類的構造函數定義爲私有方法,避免其餘函數使用該構造函數來實例化對象,只經過該類的靜態方法來獲得該類的惟一實例。
 
    對於 JS 來講,巨大的靈活性使得其能夠有多種方式實現單例模式,使用閉包方式來模擬私有數據,按照其思路可得:

  1. var single = (function(){
  2.     var unique;
  3.     function getInstance(){
  4.         if( unique === undefined ){
  5.             unique = new Construct();
  6.         }
  7.         return unique;
  8.     }
  9.     function Construct(){
  10.         // ... 生成單例的構造函數的代碼
  11.     }
  12.     return {
  13.         getInstance : getInstance
  14.     }
  15. })();
    以上,unique即是返回對象的引用,而 getInstance即是靜態方法得到實例。Construct 即是建立實例的構造函數。
    能夠經過 single.getInstance() 來獲取到單例,而且每次調用均獲取到同一個單例。這就是 單例模式 所實現的效果。
 
    不過,對於JS來講,顯然以上循規蹈矩的方式顯得過於笨重,在不一樣的場景以不一樣的方式實現單體模式正是 JS 的優點
    

    實現1: 最簡單的對象字面量


  1. var singleton = {
  2.         attr : 1,
  3.         method : function(){ return this.attr; }
  4.     }
  5. var t1 = singleton ;
  6. var t2 = singleton ;
    那麼很顯然的, t1 === t2 。
 
    十分簡單,而且很是使用,不足之處在於沒有什麼封裝性,全部的屬性方法都是暴露的。對於一些須要使用私有變量的狀況就顯得愛莫能助了。固然在對於 this 的問題上也是有必定弊端的。
 
 

    實現2:構造函數內部判斷

    其實和最初的JS實現有點相似,不過是將對是否已經存在該類的實例的判斷放入構造函數內部。

  1. function Construct(){
  2.     // 確保只有單例
  3.     if( Construct.unique !== undefined ){
  4.         return Construct.unique; 
  5.     }
  6.     // 其餘代碼
  7.     this.name = "NYF";
  8.     this.age="24";
  9.     Construct.unique = this;
  10. }
  11. var t1 = new Construct() ;
  12. var t2 = new Construct() ;
    那麼也有的, t1 === t2 。
    也是很是簡單,無非就是提出一個屬性來作判斷,可是該方式也沒有安全性,一旦我在外部修改了Construct的unique屬性,那麼單例模式也就被破壞了。
    

    實現3 : 閉包方式    

    對於大着 靈活 牌子的JS來講,任何問題都能找到 n 種答案,只不過讓我本身去掂量孰優孰劣而已,下面就簡單的舉幾個使用閉包實現單例模式的方法,無非也就是將建立了的單例緩存而已。
 

  1. var single = (function(){
  2.     var unique;
  3.     function Construct(){
  4.         // ... 生成單例的構造函數的代碼
  5.     }
  6.     unique = new Constuct();
  7.     return unique;
  8. })();
    只要 每次講 var t1 = single; var t2 = single;便可。 與對象字面量方式相似。不過相對而言更安全一點,固然也不是絕對安全。
    若是但願會用調用 single() 方式來使用,那麼也只須要將內部的 return 改成
    
    return function(){
        return unique;
    } 
    以上方式也可使用 new 的方式來進行(形式主義的趕腳)。固然這邊只是給了閉包的一種例子而已,也能夠在 Construct 中判斷單例是否存在 等等。 各類方式在各個不一樣狀況作好選着便可。
 

總結

    總的來講,單例模式相對而言是各大模式中較爲簡單的,可是單例模式也是較爲經常使用而且頗有用的模式。在JS中尤其突出(每一個對象字面量均可以看作是一個單例麼~)。
    記住,是否嚴格的只須要一個實例對象的類(雖然JS沒有類的概念),那麼就要考慮使用單例模式。
    使用數據緩存來存儲該單例,用做判斷單例是否已經生成,是單例模式主要的實現思路。
相關文章
相關標籤/搜索