iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
自我挑戰組

設計模式探索系列 第 15

[Day 15] 單例模式 (1)

  • 分享至 

  • xImage
  •  

獨一無二的物件

又來到了新的模式,這次登場的是 「單例模式」 ─當我們希望一個物件永遠只有一個實例時就會派上用場。這個模式非常簡單,可說是非常不燒腦,了解了就可以馬上記起來了!可以當作故事讀過去好好休息一下 XD
什麼時候會有這種需求呢?例如thread、註冊、logging與驅動程式等等都可能會需要,如果實例化兩個物件,會導致錯誤。
這時又有一個問題了,但這不是使用 靜態 變數就可以完成了嗎?單例模式的厲害之處在於,同時提供了 「全域接觸點」 ,又沒有全域變數的缺點─ 全域變數在應用程式開始執行時就會被建立,但有可能從不使用。要怎麼讓一個物件在被需要時才被建立,而又不會被實例化超過一個呢?

建構式可以是private的嗎?

如題,什麼情況下constructor為private的物件可以被建立呢?不妨思考一下。
要建立這個物件,必須在這個物件內呼叫它;但這個物件就還沒有被建立,簡直是那張梗圖...
https://ithelp.ithome.com.tw/upload/images/20220930/20140096eSrs7tbnSV.png
不要被牽著走了!! 仔細思考就會發現有一個漏洞!!!在物件被建構前,我們就可以用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;
        }
};

這其實潛藏了一個問題,想想看是否可以發現呢?

單例模式定義 (Singleton)

先來看看定義(真的是目前為止最白話單純了)

單例模式可以確保一個別只有一個實例,並且提供一個全域接觸點

它的特點如下:我們用一個類別自行管理自己的實例,防止其他類別可以建立(藉由private construtctor);又提供一個全域接觸點,並且可以用*惰性方式來建立。

類別圖就是如此的簡單:
https://ithelp.ithome.com.tw/upload/images/20221001/20140096LsV6dK3pFk.png

接下來,我們就來看看上面的例子會有什麼問題,真的能確保物件只被建立一個嗎??

*如果沒用到這個實例,就不會被建立,是惰性的。


上一篇
[Day 14] 工廠模式 (4)
下一篇
[Day 16] 單例模式 (2)
系列文
設計模式探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言