我眼中的單例模式

說到單例模式,網上搜索出來的結果是多如牛毛,但這不影響我也來湊熱鬧的心情。html

任何事情都是要親身去體會了,才能加深本身的理解。本着不斷學習進取的精神,我很想能夠站在牛人的肩膀上,哪怕是仰視牛人的狀況下,我也想發揮本身的餘熱。記錄下本身學習的足跡,權當本身將來細細回味也好。(不過說真的,本身試着去組織語言來介紹你的問題也好,你的產品也好,能在很大的程度上提升你的表達能力。大腦是越鍛鍊越活的東西,講話、寫做也同樣,鍥而不捨,必有收穫。總之,貴在堅持哦!)數據庫

好了,我先聲明下我參考的牛人文章出處:http://terrylee.cnblogs.com/archive/2005/12/09/293509.htmlwindows

下面來介紹模式,單例模式就是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點設計模式

 其實就是實現只有一個門能夠進入,且每次只給一我的進入。這就像之前的一位博友所舉的例子,不少人排隊去廁所蹲坑同樣,每一次只能讓一我的去蹲坑。實現單例模式的緣由,要麼是資源共享,要麼是控制資源等。所謂資源共享,就是由於單例模式保證了一個類僅有一個實例,因此你們訪問的實例是一致的。而控制資源的話,主要是減小資源的申請與釋放等。安全

牛人就是牛人,一下給出了五種實現單例模式的例子。看得我茅塞頓開,大呼過癮。多線程

 

第一種:簡單實現(惰性實例化)

 

namespace Singleton
{
    public class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }
    }

    public sealed class Singleton
    {
        private Singleton() { }

        private static Singleton instance = null;

        public static Singleton Instance
        {
            get 
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

簡單實現對於線程來講是不安全的,由於在多線程的狀況下,有可能產生多個Singleton實例。多線程的狀況下,若是多個線程都去判斷(instance == null),而它們都尚未建立實例的狀況下,就會產生多個Singleton實例。對於簡單實現來說,Singleton實例化並非應用程序啓動就建立,因此咱們把它叫作「惰性實例化」,這能避免應用程序啓動時實例化沒必要要的實例。函數

 

第二種:安全的線程

 

namespace Singleton
{
    public class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }
    }

    public sealed class Singleton
    {
        private Singleton() { }

        private static Singleton instance = null;
        private static readonly object padLock = new object();

        public static Singleton Instance
        {
            get 
            {
                lock (padLock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                    return instance;
                }
            }
        }
    }
}

安全的線程,這是對簡單實例的補充。由於提供了加鎖lock()的操做,這就能確保只有一個線程進入。可是加鎖須要增長額外的開銷,損失性能。性能

 

第三種:雙重鎖定檢查

 

namespace Singleton
{
    public class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }
    }

    public sealed class Singleton
    {
        public Singleton() { }

        private static Singleton instance = null;
private static readonly object padLock = new object(); public static Singleton Instance { get { if (instance == null) { lock (padLock) { if (instance == null) { instance = new Singleton(); } } } return instance; } } } }

雙重鎖定檢查安全的線程上面又進行了改進,主要是考慮了每次加鎖會增長額外的開銷,影響性能。因此在加鎖前再判斷Singleton有沒有被實例化。這樣,它就能減小不少的額外開銷且是線程安全的。實際上,應用程序不多須要上面方式的實現。這種方式仍然有不少缺點:沒法實現延遲初始化。大多數狀況下咱們會使用靜態初始化的方式。學習

 

第四種:靜態初始化

 

namespace Singleton
{
    public class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }
    }

    public sealed class Singleton
    {
        static readonly Singleton instance = new Singleton();

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }
}

靜態初始化是在 .NET 中實現 Singleton 的首選方法。 這段代碼有點意思,我也解讀一下。主要是講解下關鍵字吧。網站

sealed:修改類,意爲這個類不可再被繼承,防止子類被實例化而不能保證只有一個實例的問題。

private Singleton():用private 修改構造函數,能夠防止這個類在外部被實例。也就是在Singleton類外面想new Singleton()是會報編譯錯誤。

static readonly:表示只能在聲明時賦值,或是在靜態構造中賦值。

 

第五種:延遲初始化

 

namespace Singleton
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;

            if (s1 == s2)
            {
                Console.WriteLine("Objects are the same instance");
            }

            Console.Read();
        }
    }

    public sealed class Singleton
    {
        public Singleton() { }

        public static Singleton Instance
        {
            get
            {
                return Delay.DelayInstance;
            }
        }
    }

    public sealed class Delay
    {
        private static readonly Singleton delayInstance = new Singleton();
        private Delay() { }

        public static Singleton DelayInstance
        {
            get
            {
                return delayInstance;
            }
        }
    }
}

把實例化的工做交給Delay類開實現,這樣Singleton類就實現了延遲初始化。這種方式具備不少的優點,是值得推薦的一種實現方式。可是這種方式就須要開發人員記住不能使用new關鍵字實例化Singleton。

 

應用場景

 

其實不論是對於哪一個設計模式來講,咱們總會想知道何時能用到它。畢竟東西不是白學的,是貓是狗總也得帶出來溜溜。

畢竟我也使用得少,因此這裏面爲了讓網友可以看得大而全點,我摘自博友的內容以下:

1. Windows的Task Manager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想一想看,是否是呢,你能打開兩個windows task manager嗎? 不信你本身試試看哦~

2. windows的Recycle Bin(回收站)也是典型的單例應用。在整個系統運行過程當中,回收站一直維護着僅有的一個實例。

3. 網站的計數器,通常也是採用單例模式實現,不然難以同步。

4. 應用程序的日誌應用,通常均可用單例模式實現,這通常是因爲共享的日誌文件一直處於打開狀態,由於只能有一個實例去操做,不然內容很差追加。

5. Web應用的配置對象的讀取,通常也應用單例模式,這個是因爲配置文件是共享的資源。

6. 數據庫鏈接池的設計通常也是採用單例模式,由於數據庫鏈接是一種數據庫資源。數據庫軟件系統中使用數據庫鏈接池,主要是節省打開或者關閉數據庫鏈接所引發的效率損耗,這種效率上的損耗仍是很是昂貴的,由於使用單例模式來維護,就能夠大大下降這種損耗。

7. 多線程的線程池的設計通常也是採用單例模式,這是因爲線程池要方便對池中的線程進行控制。

8. 操做系統的文件系統,也是單例模式實現的具體例子,一個操做系統只能有一個文件系統。

9. HttpApplication 也是單例模式的典型應用。熟悉ASP.Net(IIS)的整個請求生命週期的人應該知道HttpApplication也是單例模式,全部的HttpModule都共享一個HttpApplication實例。

固然若是你有新的使用場景,請不吝賜教:)

至此,本文完!

相關文章
相關標籤/搜索