code style

4/04/2007

Singleton

Objective

確保類別只會有一個實體物件存在,並提供單一的存取窗口。


Motivation

當我們必須確保某些類別只需要一個實體物件存在。譬如,地球上只會有一個台灣;樂陞只會有一個Gold Dragon使用龍歌雷射;遊戲中只需要有一個怪獸工廠來產生所有個怪獸。

雖然global variable或static variable很容易存取,但是我們無法保證不會出現多個同樣類別的物件。比較好的作法就是讓類別自己管理這唯一的實體物件。並保證絕對無法生成第二個的物件。


Implementation
class Singleton {
public:
static Singleton* GetInstance();
protected:
Singleton();
private:
static Singleton* mpInstance;
};

Singleton* Singleton::GetInstance() {
if (0 == mpInstance) {
mpInstance = new Singleton;
}
return mpInstance;
}

Singleton* Singleton::mpInstance = 0;


Singleton的建構式位於protected區域,因此外界無法產生物件實體。外界只能透過GetInstance()加以存取;如果 mpInstance為0,便會產生一個新的唯一物件。此作法稱為lazy initialization:也就是等到第一次使用時才去產生物件實體。當然我們也可以給靜態變數直接建構出實體物件,那麼GetInstance() 便可以直接回傳該指標即可。不過必須考慮到一些限制:

* 確保程式在執行過程中一定會使用該類別,否則就會浪費資源。
* 該類別或許會需要執行時產生的參數,而這些參數無法在靜態變數初始化時產生。
* Singleton之間不能有dependent relation,除非我們可以保證建構物件的順序。

class Singleton {
public:
static Singleton* GetInstance() { return mpInstance; }
protected:
Singleton();
private:
static Singleton* mpInstance;
};

Singleton* Singleton::mpInstance = new Singleton;


Problem

Q: Multi-thread架構中使用Singleton會出現什麼問題?
A: 可能產生兩個Singleton。


Solution

1. 靜態初始化Singleton
2. 將GetInstance()同步化,也就是同時間只有一個thread可以進入此函式

1 則留言:

匿名 提到...

Q: Multi-thread架構中使用Singleton會出現什麼問題?
A: 可能產生兩個Singleton。
Dart:
singleton 其實用 static 變數就可以了
而且還省掉delete的問題

class Singleton {
public:
static Singleton* GetInstance();
protected:
Singleton();
};

Singleton* Singleton::GetInstance() {
static Singleton mpInstance;
return &mpInstance;
}