又來到了新的模式,這次登場的是 「單例模式」 ─當我們希望一個物件永遠只有一個實例時就會派上用場。這個模式非常簡單,可說是非常不燒腦,了解了就可以馬上記起來了!可以當作故事讀過去好好休息一下 XD
什麼時候會有這種需求呢?例如thread、註冊、logging與驅動程式等等都可能會需要,如果實例化兩個物件,會導致錯誤。
這時又有一個問題了,但這不是使用 靜態 變數就可以完成了嗎?單例模式的厲害之處在於,同時提供了 「全域接觸點」 ,又沒有全域變數的缺點─ 全域變數在應用程式開始執行時就會被建立,但有可能從不使用。要怎麼讓一個物件在被需要時才被建立,而又不會被實例化超過一個呢?
如題,什麼情況下constructor為private的物件可以被建立呢?不妨思考一下。
要建立這個物件,必須在這個物件內呼叫它;但這個物件就還沒有被建立,簡直是那張梗圖...
不要被牽著走了!! 仔細思考就會發現有一個漏洞!!!在物件被建構前,我們就可以用static來用裡面的函式啊~ 誰來跟圖片裡面的兩位說一下可以打破這個loop了XD
class MyClass
{
private:
MyClass(){}
public:
static MyClass *getInstance()
{
return new MyClass();
}
};
而如果要只有一個實例,修改成這樣是否可以達成呢?
class Singleton
{
private:
static Singleton *uniqueInstance;
Singleton(){};
public:
static Singleton *getInstance()
{
if(!uniqueInstance)
{
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
};
這其實潛藏了一個問題,想想看是否可以發現呢?
先來看看定義(真的是目前為止最白話單純了)
單例模式可以確保一個別只有一個實例,並且提供一個全域接觸點。
它的特點如下:我們用一個類別自行管理自己的實例,防止其他類別可以建立(藉由private construtctor);又提供一個全域接觸點,並且可以用*惰性方式來建立。
類別圖就是如此的簡單:
接下來,我們就來看看上面的例子會有什麼問題,真的能確保物件只被建立一個嗎??
*如果沒用到這個實例,就不會被建立,是惰性的。