JavaScript 設計模式:單體模式 ( Singleton )


  • Singleton 的概念是讓特定的 class 只有唯一的實體
  • 當第二次使用同一個 class 建立物件,會得到和第一次建立時相同的物件

使用物件實字建立物件

var obj = {
    myProp: 1
};

var obj1 = {
    myProp: 1
};

obj === obj1; // false

每次使用物件實字建立物件,其實都是在建立 singleton,就算建立了相同的內容與成員,這兩個物件也不會相等

實現方式

  1. 用全域變數儲存實體
    • 缺點:非常容易被覆蓋掉,千萬不要使用這種方式
  2. 用建構式的靜態屬性儲存實體
    • 缺點:有機會被更動,但機率比全域變數來得低
  3. 用 closure 的特性儲存實體
    • 優點:實體為 private,無法在建構式外修改
    • 缺點:儲存在記憶體空間

儲存在靜態屬性中的實體

function Universe() {
    // 判斷是否已有現有的實體
    if (typeof Universe.instance === "object") {
        return Universe.instance;
    }

    this.startTime = 0;
    this.bang = "Big";

    // 快取
    Universe.instance = this;
}

var uni1 = new Universe();
var uni2 = new Universe(); // uni2 會得到相同的 instance

// 缺點,有機會被異動
Universe.instance = {foo: 'bye'};

var uni3 = new Universe();
uni1 === uni3; // false

儲存在 Closure 中的實體

作法一

function Universe() {
  var instance = this; // 快取的實體
  this.startTime = 0;

  // 重新定義建構式
  Universe = function() {
    return instance;
  }
}

var uni = new Universe();
var uni2 = new Universe();

uni === uni2; // true

缺點,重新定義的函式會失去之前定義的屬性

function Universe() {
  var instance = this; // 快取的實體
  this.startTime = 0;

  // 重新定義建構式
  Universe = function() {
    return instance;
  }
}

Universe.prototype.nothing = true;

var uni = new Universe();

Universe.prototype.everything = true;

var uni2 = new Universe();

uni.nothing; // true
uni.everything; // true
uni2.nothing; // undefined
uni2.everything; // undefined

uni.constructor.name; // Universe

uni.constructor === Universe; // false

作法二:書中建議的做法,使用立即函式包住建構式與實體

var Universe;

(function() {
  var instance;
  Universe = function() {
    if (instance) { 
      return instance; // 第二次呼叫建構式則回傳 private 的 instance
    }

    instance = this; // 第一次呼叫建構式會建立一個物件,並指派給 instance

    this.startTime = 0;
  };
})();
#singleton #javascript #designpattern






你可能感興趣的文章

人性較量Day06~量化資訊

人性較量Day06~量化資訊

C++ 指標*跟&的用法  (3)

C++ 指標*跟&的用法 (3)

Click and Drag to Scroll

Click and Drag to Scroll






留言討論