[Design Pattern] 獨體模式(Singleton Pattern) 介紹

  • 7438
  • 0
  • C#
  • 2020-07-27

不久前剛好被學弟問到關於設計模式的問題,覺得滿有趣的,所以放上來與大家分享一下。

 

獨體模式其實大家很常使用到,但或許大家不知道他叫獨體模式。

獨體模式又稱為單例模式,目的是為了讓

該物件只能實體化一次,往後每次調用都是相同的物件

而在介紹之前,我們先談談這個獨體模式,他可以使用在哪些情況下。

畢竟我們如果連一開始在何處使用都不知道,那在學習上也只會很空泛,是吧?

獨體模式使用場景

前面剛剛有說過,獨體模式相信有在寫程式的一定都有使用過,只是自己不知道它也是23種設計模式中的其中一種罷了。

他的應用範圍相當廣泛,隨便舉幾個例子:

1.外部資源

在我們撰寫多執行緒的時候,一定都會遇到當資源有限的情況下,只能有一個Client可以取得該資源時,同一時間我們該如何去判斷只有一位Client可以獲取資源。
這就是獨體模式。


2. Windows的Task Manager(任務管理器)

相信大家都有開啟過Windows的TaskManager吧?其實它就是很典型的獨體模式,我們可以操作看看,你會發現在同一時間內我們無法打開兩個windows task manager

有興趣的可以自己試試看哦~  

3.網站的計數器

一般我們在統計該網站的訪問人數時,也是採用獨體模式實現。

假設該站總瀏覽次數為1000次,在同一時間內,有一個以上的Client瀏覽了該網站,如果我們不能及時的將總瀏覽次數進行Lock,那麼同一時間內我們該如何計算瀏覽次數+1呢是吧?

簡單介紹完使用場景後,接下來我們來介紹一下該如何使用獨體模式呢?

在這邊一樣透過幾個程式碼的範例來講解一下獨體模式的使用方式:

1.透過自訂函式來控制該物件的建立 

    /// <summary>
    /// 透過自訂函數來初始化該物件
    /// </summary>
    class Singleton
    {
        private static Singleton singleton;

        private Singleton()//禁止外部直接實體化該物件
        {
        }

        public static Singleton GetInstance()
        {
            if (singleton == null)
            {
                singleton = new Singleton();
            }
            return singleton;
        }
    }

我們可以透過自訂函式來將該物件進行實體化,當物件尚未被實體化時,才執行 new 關鍵字

這是第一種最基本的方式,我們禁止外部可以實體化該物件,並由自訂函式來實現,此種方式能確保在程式的生命週期中,只會有一個實體產生。

 

2.透過自訂函式來控制該物件的建立(使用sealedreadonly關鍵字限定物件多次建立)

    /// <summary>
    /// 利用sealed 限定該類別不能被繼承 透過readonly限定初始化時機
    /// </summary>
    sealed class SealedSingleton
    {
        private static readonly SealedSingleton instance = new SealedSingleton();
        private SealedSingleton() { }
        public static SealedSingleton GetInstance()
        {
            return instance;
        }
    }

這個例子與第一種相同,都是透過自訂函式來進行該物件的調用。不過唯一不一樣的是,在這邊我們利用了sealedreadonly關鍵字。

我們都知道,類別一但被繼承的時候,會自動初始化父類別的欄位以及建構元的部分,因此我們加上sealed關鍵字,讓他不允許被繼承

如此一來,我們能確保目前第一步的該物件只會有一個實體存在。

接著在欄位變數的初始化上,我們將在物件前面加上了 readonly ,讓該變數只能在欄位或是建構元當中進行物件的初始化,其餘地方禁止進行初始化。

會做這一步的用途在於,限定我們的物件在這一隻程式底下只會有一個instance產生。

3.在多執行緒上,確保只有一個物件實體存在

 /// <summary>
    /// 利用lock來確保同一時間只會有一個實體產生
    /// </summary>
    class SingletonLock
{
    private static SingletonLock instance;
    private static readonly object syncRoot = new object();
    private SingletonLock()
    {
    }
    public static SingletonLock GetInstance()
    {

        if (instance == null) //確保當前沒有這個物件存在
        {
            lock (syncRoot)//鎖住當前狀態
            {
                if (instance == null)//再次確認該物件不存在
                {
                    instance = new SingletonLock();
                }
            }
        }
        return instance;
    }

最後一種方式則是在當我們使用  Multi-Thread 時,為了確保只會有一個物件實體存在,我們可以透過lock 這個關鍵字

確保同一時間不會有一個以上的物件實體存在。

使用方法與 java的synchronized 相同,在這邊就不多做說明了。

 

以上就是獨體模式的相關介紹以及各種的使用方式。

 

以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教:)

有任何家教、案子 或技術相關問題 請都歡迎聯繫我

http://www.zhenghui.idv.tw/