欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript中實現(xiàn)單體模式分享

 更新時間:2015年01月29日 09:20:48   投稿:junjie  
這篇文章主要介紹了JavaScript中實現(xiàn)單體模式分享,單體模式的定義:單體是一個用來劃分命名空間并將一批相關(guān)方法和屬性組織在一起的對象,如果它能夠被實例化,那么只能被實例化一次,需要的朋友可以參考下

單體模式作為一種軟件開發(fā)模式在眾多面向?qū)ο笳Z言中得到了廣泛的使用,在javascript中,單體模式也是使用非常廣泛的,但是由于javascript語言擁有其獨特的面向?qū)ο蠓绞?,?dǎo)致其和一些傳統(tǒng)面向?qū)ο笳Z言雖然在單體模式的思想上是一致的,但是實現(xiàn)起來還是有差異的。

首先來看看傳統(tǒng)面向?qū)ο笳Z言對于單體模式的定義:單體模式是只能被實例化一次并且可以通過一個眾所周知的訪問點來訪問的類。這個定義有兩點突出了傳統(tǒng)面向?qū)ο笳Z言的特征,即類和實例化,所以對于傳統(tǒng)面向?qū)ο笳Z言來講,單體模式是建立在其類和實例化的自然特性之上的,即使用關(guān)鍵字class定義一個類,該類可通過new關(guān)鍵字來實例化,但是需要保證每次被new實例化之后得到的都是同一個實例或者說只能通過new來調(diào)用其構(gòu)造函數(shù)一次。

再來看看javascript中對于單體模式的定義:單體是一個用來劃分命名空間并將一批相關(guān)方法和屬性組織在一起的對象,如果它能夠被實例化,那么只能被實例化一次。對比上面的定義,你會發(fā)現(xiàn)這里的單體定義將其實質(zhì)定義為對象,而不是傳統(tǒng)面向?qū)ο笳Z言中的類,這也表明了javascript這門語言是基于對象的。同時后面又指出,如果能夠被實例化,這說明了在javascript中單體定義應(yīng)該有好幾種方式,存在一種或幾種能夠被實例化即使用new關(guān)鍵字來創(chuàng)建單體對象的方式,但是這種方式不是javascript自身的自然特征,因為使用new關(guān)鍵字創(chuàng)造出來的對象,實際上都是通過function來模擬定義其構(gòu)造函數(shù)的(雖然ES6開始支持class關(guān)鍵字了,但是目前還沒有得到瀏覽器廣泛支持),那么如何使用javascript的自然特征來實現(xiàn)單體模式呢?

var Singleton={
  attribute1:true,
  attribute2:10,
  method1:function(){

  },
  method2:function(arg){

  }
}

這里定義了一個對象Singleton,內(nèi)部包含若干屬性和方法,將其包含在頁面中,js載入的時候就創(chuàng)建了這個對象,在調(diào)用時使用Singleton.method1來調(diào)用,它的實例化是隨著頁面載入js解析執(zhí)行過程中完成的,我們并沒有使用new關(guān)鍵字來實例化這個對象,這也是javascript中實現(xiàn)單體模式和傳統(tǒng)面向?qū)ο笳Z言一個很大的不同。這種方式更為簡單易于理解。但是這種方式存在若干缺點,一個很明顯的缺點是它并沒有提供命名空間,其他程序員如果在頁面中也定義了一個Singleton變量,那么很容易改寫和混淆這個單體對象,于是針對這個問題,將其改寫如下:

var mySpace={};
mySpace.Singleton={
  attribute1:true,
  attribute2:10,
  method1:function(){

  },
  method2:function(arg){

  }
}


這里首先定義了一個mySpace的命名空間,然后將單體對象Singleton掛載在這個對象的下面,這大大減少了和其他程序員沖突以及誤操作的可能,即使其他人在全局作用域中定義一個Singleton變量,也不會污染到這個單體對象,這就實現(xiàn)了前面定義中所說的劃分命名空間并且將一些相關(guān)屬性和方法組織在一起的功能。

這個方法依然存在缺點,這個單體對象的所有屬性和方法都是共有的,外部可隨時訪問和修改,于是采用閉包來模擬私有屬性和方法,如下:

mySpace.Singleton=(function(){
  var privateAttribute1=false;
  var privateAttribute1=[1,2,3];
  function privateMethod1(){

  }
  function privateMethod2(){

  }

  return {
  publicAttribute1:true,
  publicAttribute2:10,
  publicMethod1:function(){
    privateAttribute1=true;
    privateMethod1();
  },
  publicMethod2:function(arg){
    privateAttribute1=[4,5,6];
    privateMethod2();
  }

  }

})();


在這里我們直接給該單體對象賦值了一個匿名自執(zhí)行的函數(shù),在該函數(shù)中使用var和function關(guān)鍵字分別來定義其私有屬性和方法,這些在函數(shù)外部(單體對象外部)是無法直接訪問的,因為函數(shù)一執(zhí)行完畢,其內(nèi)部作用域的空間就會被回收,這也就是能夠利用閉包來模擬私有屬性和方法的原因所在。在該函數(shù)(閉包)中,同時最終返回一個對象,這個對象中包含一些公有方法和屬性,在外部可以直接調(diào)用,同時這些公有方法由于定義在函數(shù)內(nèi)部,所以可以調(diào)用其私有屬性和方法,但是外界只能通過返回的公有方法和屬性來完成某些操作,不能夠直接調(diào)用Singleton.privateMethod1這些屬性。這就使得該單體對象既隔離了外界去直接訪問其私有屬性和方法,又提供給外界一些共有屬性和方法去完成某些操作。

這種匿名函數(shù)自執(zhí)行所構(gòu)造的單體模式在很多js庫中被廣泛使用,但是依然存在一個問題,如果我們在載入頁面的時候并不需要用到該對象,而且該對象的創(chuàng)建比較耗費開銷(如需要進行大量計算或需要多次訪問dom樹及其屬性等)時,合理的做法是需要它的時候再去創(chuàng)建它,而不是隨著js的解析執(zhí)行直接去創(chuàng)建,這種概念被稱之為惰性加載(lazy loading),于是修改以上代碼如下:

mySpace.Singleton=(function(){
    var uniqueInstance;
    function constructor(){
      var privateAttribute1=false;
      var privateAttribute1=[1,2,3];
      function privateMethod1(){
      }
      function privateMethod2(){
      }
      return {
        publicAttribute1:true,
        publicAttribute2:10,
        publicMethod1:function(){
          privateAttribute1=true;
          privateMethod1();
        },
        publicMethod2:function(arg){
          privateAttribute1=[4,5,6];
          privateMethod2();
        }

      }
    }

    return {
      getInstance:function(){
       if(!uniqueInstance){
         uniqueInstance=constructor();
       }
        return uniqueInstance;
      }
    }

  })();

這里首先在匿名函數(shù)中定義了一個私有變量uniqueInstance,作為一個判斷單體對象是否被創(chuàng)建出來的句柄,然后將剛才所有對單體對象定義的屬性和方法都放在一個名為constructor的函數(shù)中,只有該函數(shù)調(diào)用了,才會創(chuàng)造出該單體對象,否則不會直接創(chuàng)建它。然后,返回一個對象,其包含一個getInstance方法,該方法是供外部調(diào)用的,調(diào)用該方法的時候首先判斷該單體對象是否存在,如果存在就直接返回它,否則調(diào)用constructor函數(shù)構(gòu)造這個單體對象再返回它。最后如果我們調(diào)用該單體對象的某個方法,需要使用mySpace.Singleton.getInstance().publicMethod1(),這里,只有我們這樣調(diào)用的時候才會創(chuàng)建這個單體對象,否則該單體對象是不會被自動創(chuàng)建的,這實際上就實現(xiàn)了按需加載或者惰性加載。

相關(guān)文章

最新評論