Singleton Pattern帶來的是保證一個class只有一個實體,無法產生第二個第三個... 使用這種模式的概念是系統中永遠只會唯一存在,如OS kernal、program core或hardward controller等。C++實作如下:
1. default constructor宣告為private並實作(空內容也沒關係)。因此實體只能在內部產生,外部無法取得建構子。
2. copy constructor and operator=宣告為private並不實作。宣告為private使得外部無法取得函式原型,不實作它是因為不需要,並且令編譯失敗(若使用到copy constructor or operator=,因為沒有實作,會產生連結錯誤,確保不能複製物件)
3. destructor宣告為private,防止外部刪除實體。(這一點可商議。若getIOController()回傳IOController*,則destructor必須宣告為private;若getIOController回傳IOController&,那這點可忽略)
另外值得注意的是getIOController()中宣告static IOController IOController物件,這樣寫法是依賴編譯器的一個規則,"函式內的靜態物件在該函式第一次執行時被初始化",所以getIOController從末被呼叫時,IOController沒有被初始化,效能並沒有降低。
提到唯一性一定會想起靜態函式和靜態物件,那Singleton可以利用靜態來實作嗎
class IOController {
private:
IOController() { /*implement*/ }
IOController(const Core&);
IOController& operator=(const IOController&);
virtual ~IOController();
public:
static IOController& getIOController() {
static IOController IOController;
return IOController;
}
void memberFunctionA() {}
void memberFunctionA() {}
private:
MemberData A;
MemberData B;
};
一個正確的Singleton應該確保唯一性,C++確保唯一的保護措施有三點:1. default constructor宣告為private並實作(空內容也沒關係)。因此實體只能在內部產生,外部無法取得建構子。
2. copy constructor and operator=宣告為private並不實作。宣告為private使得外部無法取得函式原型,不實作它是因為不需要,並且令編譯失敗(若使用到copy constructor or operator=,因為沒有實作,會產生連結錯誤,確保不能複製物件)
3. destructor宣告為private,防止外部刪除實體。(這一點可商議。若getIOController()回傳IOController*,則destructor必須宣告為private;若getIOController回傳IOController&,那這點可忽略)
另外值得注意的是getIOController()中宣告static IOController IOController物件,這樣寫法是依賴編譯器的一個規則,"函式內的靜態物件在該函式第一次執行時被初始化",所以getIOController從末被呼叫時,IOController沒有被初始化,效能並沒有降低。
提到唯一性一定會想起靜態函式和靜態物件,那Singleton可以利用靜態來實作嗎
class IOController {
public:
static void memberFunctionA() {}
static void memberFunctionA() {}
// ...
private:
static MemberData A;
static MemberData B;
// ...
};
這樣看似沒甚麼問題,也不需要宣告private之類有的沒的。但是這情況下會缺乏擴充性,假如現在需要第二代IOController2,且保留IOController,視不同情況選擇使用。這樣實作IOController2會很困難,因為靜態函式不能成為虛擬函式,所以IOController和IOController2不能使用多型。若以原來的範例則可以輕鬆解決。class IOController2 : public IOController {
private:
IOController2() { /*implement*/ }
IOController2(const IOController2&);
IOController2& operator=(const IOController2&);
virtual ~IOController2();
public:
static IOController2& getIOController2() {
static IOController2 IOController2;
return IOController2;
}
void memberFunctionA() {}
void memberFunctionB() {}
private:
MemberData C;
MemberData D;
};
void main {
bool condition = true;
Core& core = condition? IOController2::getIOController2(): IOController::getIOController();
core.memberFunctionA();
core.memberFunctionB();
}
