在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 單例模式
中介者模式
MVVM
亨元模式
設(shè)計模式分類概覽表
ES Harmony
組合模式
CommonJS
jQuery 插件的設(shè)計模式
外觀模式
觀察者模式
建造者模式
構(gòu)造器模式
外觀模式
簡介
AMD
原型模式
設(shè)計模式的分類
觀察者模式
命名空間模式
代理模式
編寫設(shè)計模式
適配器模式
反模式
什么是設(shè)計模式
模塊化模式
MVC
Mixin 模式
裝飾模式
設(shè)計模式的結(jié)構(gòu)
單例模式
迭代器模式
命令模式
工廠模式
MVP
暴露模塊模式
惰性初始模式

單例模式

單例模式之所以這么叫,是因為它限制一個類只能有一個實例化對象。經(jīng)典的實現(xiàn)方式是,創(chuàng)建一個類,這個類包含一個方法,這個方法在沒有對象存在的情況下,將會創(chuàng)建一個新的實例對象。如果對象存在,這個方法只是返回這個對象的引用。

單例和靜態(tài)類不同,因為我們可以退出單例的初始化時間。通常這樣做是因為,在初始化的時候需要一些額外的信息,而這些信息在聲明的時候無法得知。對于并不知曉對單例模式引用的代碼來講,單例模式?jīng)]有為它們提供一種方式可以簡單的獲取單例模式。這是因為,單例模式既不返回對象也不返回類,它只返回一種結(jié)構(gòu)??梢灶惐乳]包中的變量不是閉包-提供閉包的函數(shù)域是閉包(繞進去了)。

在JavaScript語言中, 單例服務(wù)作為一個從全局空間的代碼實現(xiàn)中隔離出來共享的資源空間是為了提供一個單獨的函數(shù)訪問指針。

我們能像這樣實現(xiàn)一個單例:

var mySingleton = (function () {

  // Instance stores a reference to the Singleton
  var instance;

  function init() {

    // 單例

    // 私有方法和變量
    function privateMethod(){
        console.log( "I am private" );
    }

    var privateVariable = "Im also private";

    var privateRandomNumber = Math.random();

    return {

      // 共有方法和變量
      publicMethod: function () {
        console.log( "The public can see me!" );
      },

      publicProperty: "I am also public",

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // 如果存在獲取此單例實例,如果不存在創(chuàng)建一個單例實例
    getInstance: function () {

      if ( !instance ) {
        instance = init();
      }

      return instance;
    }

  };

})();

var myBadSingleton = (function () {

  // 存儲單例實例的引用
  var instance;

  function init() {

    // 單例

    var privateRandomNumber = Math.random();

    return {

      getRandomNumber: function() {
        return privateRandomNumber;
      }

    };

  };

  return {

    // 總是創(chuàng)建一個新的實例
    getInstance: function () {

      instance = init();

      return instance;
    }

  };

})();

// 使用:

var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true

var badSingleA = myBadSingleton.getInstance();
var badSingleB = myBadSingleton.getInstance();
console.log( badSingleA.getRandomNumber() !== badSingleB.getRandomNumber() ); // true

創(chuàng)建一個全局訪問的單例實例 (通常通過 MySingleton.getInstance()) 因為我們不能(至少在靜態(tài)語言中) 直接調(diào)用 new MySingleton() 創(chuàng)建實例. 這在JavaScript語言中是不可能的。

在四人幫(GoF)的書里面,單例模式的應(yīng)用描述如下:

  • 每個類只有一個實例,這個實例必須通過一個廣為人知的接口,來被客戶訪問。
  • 子類如果要擴展這個唯一的實例,客戶可以不用修改代碼就能使用這個擴展后的實例。

關(guān)于第二點,可以參考如下的實例,我們需要這樣編碼:

mySingleton.getInstance = function(){
  if ( this._instance == null ) {
    if ( isFoo() ) {
       this._instance = new FooSingleton();
    } else {
       this._instance = new BasicSingleton();
    }
  }
  return this._instance;
};

在這里,getInstance 有點類似于工廠方法,我們不需要去更新每個訪問單例的代碼。FooSingleton可以是BasicSinglton的子類,并且實現(xiàn)了相同的接口。

為什么對于單例模式來講,延遲執(zhí)行執(zhí)行這么重要?

在c++代碼中,單例模式將不可預(yù)知的動態(tài)初始化順序問題隔離掉,將控制權(quán)返回給程序員。

區(qū)分類的靜態(tài)實例和單例模式很重要:盡管單例模式可以被實現(xiàn)成一個靜態(tài)實例,但是單例可以懶構(gòu)造,在真正用到之前,單例模式不需要分配資源或者內(nèi)存。

如果我們有個靜態(tài)對象可以被直接初始化,我們需要保證代碼總是以同樣的順序執(zhí)行(例如 汽車需要輪胎先初始化)當你有很多源文件的時候,這種方式?jīng)]有可擴展性。

單例模式和靜態(tài)對象都很有用,但是不能濫用-同樣的我們也不能濫用其它模式。

在實踐中,當一個對象需要和另外的對象進行跨系統(tǒng)協(xié)作的時候,單例模式很有用。下面是一個單例模式在這種情況下使用的例子:

var SingletonTester = (function () {

  // options: an object containing configuration options for the singleton
  // e.g var options = { name: "test", pointX: 5}; 
  function Singleton( options )  {

    // set options to the options supplied
    // or an empty object if none are provided
    options = options || {};

    // set some properties for our singleton
    this.name = "SingletonTester";

    this.pointX = options.pointX || 6;

    this.pointY = options.pointY || 10; 

  }

  // our instance holder 
  var instance;

  // an emulation of static variables and methods
  var _static  = {  

    name:  "SingletonTester",

    // Method for getting an instance. It returns
    // a singleton instance of a singleton object
    getInstance:  function( options ) {   
      if( instance  ===  undefined )  {    
        instance = new Singleton( options );   
      }   

      return  instance; 

    } 
  }; 

  return  _static;

})();

var singletonTest  =  SingletonTester.getInstance({
  pointX:  5
});

// Log the output of pointX just to verify it is correct
// Outputs: 5
console.log( singletonTest.pointX );

盡管單例模式有著合理的使用需求,但是通常當我們發(fā)現(xiàn)自己需要在javascript使用它的時候,這是一種信號,表明我們可能需要去重新評估自己的設(shè)計。

這通常表明系統(tǒng)中的模塊要么緊耦合要么邏輯過于分散在代碼庫的多個部分。單例模式更難測試,因為可能有多種多樣的問題出現(xiàn),例如隱藏的依賴關(guān)系,很難去創(chuàng)建多個實例,很難清理依賴關(guān)系,等等。

要想進一步了解關(guān)于單例的信息,可以讀讀 Miller Medeiros 推薦的這篇非常棒的關(guān)于單例模式以及單例模式各種各樣問題的文章,也可以看看這篇文章的評論,這些評論討論了單例模式是怎樣增加了模塊間的緊耦合。我很樂意去支持這些推薦,因為這兩篇文章提出了很多關(guān)于單例模式重要的觀點,而這些觀點是很值得重視的。

上一篇:原型模式下一篇:Mixin 模式