乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      博客園 - 探索設(shè)計(jì)模式(二):深入淺出單件模式(Sigleton Pattern)

       心之所指 2006-01-23

      深入淺出單件模式(Sigleton Pattern

      ——探索設(shè)計(jì)模式系列之二

      Terrylee,20051207

      概述

      Sigleton模式要求一個類有且僅有一個實(shí)例,并且提供了一個全局的訪問點(diǎn)。這就提出了一個問題:如何繞過常規(guī)的構(gòu)造器,提供一種機(jī)制來保證一個類只有一個實(shí)例?客戶程序在調(diào)用某一個類時,它是不會考慮這個類是否只能有一個實(shí)例等問題的,所以,這應(yīng)該是類設(shè)計(jì)者的責(zé)任,而不是類使用者的責(zé)任。

      從另一個角度來說,Sigleton模式其實(shí)也是一種職責(zé)型模式。因?yàn)槲覀儎?chuàng)建了一個對象,這個對象扮演了獨(dú)一無二的角色,在這個單獨(dú)的對象實(shí)例中,它集中了它所屬類的所有權(quán)力,同時它也肩負(fù)了行使這種權(quán)力的職責(zé)!

      意圖

      保證一個類僅有一個實(shí)例,并提供一個訪問它的全局訪問點(diǎn)。

      模型圖

      邏輯模型圖:

      物理模型圖:

      生活中的例子

      美國總統(tǒng)的職位是Sigleton,美國憲法規(guī)定了總統(tǒng)的選舉,任期以及繼任的順序。這樣,在任何時刻只能由一個現(xiàn)任的總統(tǒng)。無論現(xiàn)任總統(tǒng)的身份為何,其頭銜"美利堅(jiān)合眾國總統(tǒng)"是訪問這個職位的人的一個全局的訪問點(diǎn)。

      五種實(shí)現(xiàn)

      1.簡單實(shí)現(xiàn)

       1public sealed class Singleton
       2{
       3    static Singleton instance=null;
       4
       5    Singleton()
       6    {
       7    }

       8
       9    public static Singleton Instance
      10    {
      11        get
      12        {
      13            if (instance==null)
      14            {
      15                instance = new Singleton();
      16            }

      17            return instance;
      18        }

      19    }

      20}

      這種方式的實(shí)現(xiàn)對于線程來說并不是安全的,因?yàn)樵诙嗑€程的環(huán)境下有可能得到Sigleton類的多個實(shí)例。如果同時有兩個線程去判斷(instance == null),并且得到的結(jié)果為真,這時兩個線程都會創(chuàng)建類Sigleton的實(shí)例,這樣就違背了Sigleton模式的原則。實(shí)際上在上述代碼中,有可能在計(jì)算出表達(dá)式的值之前,對象實(shí)例已經(jīng)被創(chuàng)建,但是內(nèi)存模型并不能保證對象實(shí)例在第二個線程創(chuàng)建之前被發(fā)現(xiàn)。

      該實(shí)現(xiàn)方式主要有兩個優(yōu)點(diǎn):

      l         由于實(shí)例是在 Instance 屬性方法內(nèi)部創(chuàng)建的,因此類可以使用附加功能(例如,對子類進(jìn)行實(shí)例化),即使它可能引入不想要的依賴性。

      l         直到對象要求產(chǎn)生一個實(shí)例才執(zhí)行實(shí)例化;這種方法稱為“惰性實(shí)例化”。惰性實(shí)例化避免了在應(yīng)用程序啟動時實(shí)例化不必要的 singleton。

      2.安全的線程

       1public sealed class Singleton
       2{
       3    static Singleton instance=null;
       4    static readonly object padlock = new object();
       5
       6    Singleton()
       7    {
       8    }

       9
      10    public static Singleton Instance
      11    {
      12        get
      13        {
      14            lock (padlock)
      15            {
      16                if (instance==null)
      17                {
      18                    instance = new Singleton();
      19                }

      20                return instance;
      21            }

      22        }

      23    }

      24}

      25
      26

      這種方式的實(shí)現(xiàn)對于線程來說是安全的。我們首先創(chuàng)建了一個進(jìn)程輔助對象,線程在進(jìn)入時先對輔助對象加鎖然后再檢測對象是否被創(chuàng)建,這樣可以確保只有一個實(shí)例被創(chuàng)建,因?yàn)樵谕粋€時刻加了鎖的那部分程序只有一個線程可以進(jìn)入。這種情況下,對象實(shí)例由最先進(jìn)入的那個線程創(chuàng)建,后來的線程在進(jìn)入時(instence == null)為假,不會再去創(chuàng)建對象實(shí)例了。但是這種實(shí)現(xiàn)方式增加了額外的開銷,損失了性能。

      3.雙重鎖定

       1public sealed class Singleton
       2{
       3    static Singleton instance=null;
       4    static readonly object padlock = new object();
       5
       6    Singleton()
       7    {
       8    }

       9
      10    public static Singleton Instance
      11    {
      12        get
      13        {
      14            if (instance==null)
      15            {
      16                lock (padlock)
      17                {
      18                    if (instance==null)
      19                    {
      20                        instance = new Singleton();
      21                    }

      22                }

      23            }

      24            return instance;
      25        }

      26    }

      27}

      28

      這種實(shí)現(xiàn)方式對多線程來說是安全的,同時線程不是每次都加鎖,只有判斷對象實(shí)例沒有被創(chuàng)建時它才加鎖,有了我們上面第一部分的里面的分析,我們知道,加鎖后還得再進(jìn)行對象是否已被創(chuàng)建的判斷。它解決了線程并發(fā)問題,同時避免在每個 Instance 屬性方法的調(diào)用中都出現(xiàn)獨(dú)占鎖定。它還允許您將實(shí)例化延遲到第一次訪問對象時發(fā)生。實(shí)際上,應(yīng)用程序很少需要這種類型的實(shí)現(xiàn)。大多數(shù)情況下我們會用靜態(tài)初始化。這種方式仍然有很多缺點(diǎn):無法實(shí)現(xiàn)延遲初始化。

      4.靜態(tài)初始化

       1public sealed class Singleton
       2{
       3    static readonly Singleton instance=new Singleton();
       4
       5    static Singleton()
       6    {
       7    }

       8
       9    Singleton()
      10    {
      11    }

      12
      13    public static Singleton Instance
      14    {
      15        get
      16        {
      17            return instance;
      18        }

      19    }

      20}

      21

      看到上面這段富有戲劇性的代碼,我們可能會產(chǎn)生懷疑,這還是Sigleton模式嗎?在此實(shí)現(xiàn)中,將在第一次引用類的任何成員時創(chuàng)建實(shí)例。公共語言運(yùn)行庫負(fù)責(zé)處理變量初始化。該類標(biāo)記為 sealed 以阻止發(fā)生派生,而派生可能會增加實(shí)例。此外,變量標(biāo)記為 readonly,這意味著只能在靜態(tài)初始化期間(此處顯示的示例)或在類構(gòu)造函數(shù)中分配變量。

      該實(shí)現(xiàn)與前面的示例類似,不同之處在于它依賴公共語言運(yùn)行庫來初始化變量。它仍然可以用來解決 Singleton 模式試圖解決的兩個基本問題:全局訪問和實(shí)例化控制。公共靜態(tài)屬性為訪問實(shí)例提供了一個全局訪問點(diǎn)。此外,由于構(gòu)造函數(shù)是私有的,因此不能在類本身以外實(shí)例化 Singleton 類;因此,變量引用的是可以在系統(tǒng)中存在的唯一的實(shí)例。

      由于 Singleton 實(shí)例被私有靜態(tài)成員變量引用,因此在類首次被對 Instance 屬性的調(diào)用所引用之前,不會發(fā)生實(shí)例化。

      這種方法唯一的潛在缺點(diǎn)是,您對實(shí)例化機(jī)制的控制權(quán)較少。在 Design Patterns 形式中,您能夠在實(shí)例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)。由于在此解決方案中由 .NET Framework 負(fù)責(zé)執(zhí)行初始化,因此您沒有這些選項(xiàng)。在大多數(shù)情況下,靜態(tài)初始化是在 .NET 中實(shí)現(xiàn) Singleton 的首選方法。

      5.延遲初始化

       1public sealed class Singleton
       2{
       3    Singleton()
       4    {
       5    }

       6
       7    public static Singleton Instance
       8    {
       9        get
      10        {
      11            return Nested.instance;
      12        }

      13    }

      14    
      15    class Nested
      16    {
      17        static Nested()
      18        {
      19        }

      20
      21        internal static readonly Singleton instance = new Singleton();
      22    }

      23}

      24

      這里,初始化工作有Nested類的一個靜態(tài)成員來完成,這樣就實(shí)現(xiàn)了延遲初始化,并具有很多的優(yōu)勢,是值得推薦的一種實(shí)

      現(xiàn)方式。

      實(shí)現(xiàn)要點(diǎn)

      l        Sigleton模式是限制而不是改進(jìn)類的創(chuàng)建。

      l         Sigleton類中的實(shí)例構(gòu)造器可以設(shè)置為Protected以允許子類派生。

      l         Sigleton模式一般不要支持Icloneable接口,因?yàn)檫@可能導(dǎo)致多個對象實(shí)例,與Sigleton模式的初衷違背。

      l         Sigleton模式一般不要支持序列化,這也有可能導(dǎo)致多個對象實(shí)例,這也與Sigleton模式的初衷違背。

      l         Sigleton只考慮了對象創(chuàng)建的管理,沒有考慮到銷毀的管理,就支持垃圾回收的平臺和對象的開銷來講,我們一般沒必要對其銷毀進(jìn)行特殊的管理。

      l         理解和擴(kuò)展Sigleton模式的核心是“如何控制用戶使用new對一個類的構(gòu)造器的任意調(diào)用”。

      l         可以很簡單的修改一個Sigleton,使它有少數(shù)幾個實(shí)例,這樣做是允許的而且是有意義的。

      優(yōu)點(diǎn)

      l         實(shí)例控制:Singleton 會阻止其他對象實(shí)例化其自己的 Singleton 對象的副本,從而確保所有對象都訪問唯一實(shí)例

      l         靈活性:因?yàn)轭惪刂屏藢?shí)例化過程,所以類可以更加靈活修改實(shí)例化過程

      缺點(diǎn)

      l         開銷:雖然數(shù)量很少,但如果每次對象請求引用時都要檢查是否存在類的實(shí)例,將仍然需要一些開銷。可以通過使用靜態(tài)初始化解決此問題,上面的五種實(shí)現(xiàn)方式中已經(jīng)說過了。

      l          可能的開發(fā)混淆:使用 singleton 對象(尤其在類庫中定義的對象)時,開發(fā)人員必須記住自己不能使用 new 關(guān)鍵字實(shí)例化對象。因?yàn)榭赡軣o法訪問庫源代碼,因此應(yīng)用程序開發(fā)人員可能會意外發(fā)現(xiàn)自己無法直接實(shí)例化此類。

      l         對象的生存期:Singleton 不能解決刪除單個對象的問題。在提供內(nèi)存管理的語言中(例如基于 .NET Framework 的語言),只有 Singleton 類能夠?qū)е聦?shí)例被取消分配,因?yàn)樗瑢υ搶?shí)例的私有引用。在某些語言中(如 C++),其他類可以刪除
      對象實(shí)例,但這樣會導(dǎo)致 Singleton 類中出現(xiàn)懸浮引用。

      適用性

      l         當(dāng)類只能有一個實(shí)例而且客戶可以從一個眾所周知的訪問點(diǎn)訪問它時。

      l         當(dāng)這個唯一實(shí)例應(yīng)該是通過子類化可擴(kuò)展的,并且客戶應(yīng)該無需更改代碼就能使用一個擴(kuò)展的實(shí)例時。

      應(yīng)用場景

      l         每臺計(jì)算機(jī)可以有若干個打印機(jī),但只能有一個Printer Spooler,避免兩個打印作業(yè)同時輸出到打印機(jī)。
      (摘自呂震宇的
      C#設(shè)計(jì)模式(7)-Singleton Pattern

      l         PC機(jī)中可能有幾個串口,但只能有一個COM1口的實(shí)例。

      l         系統(tǒng)中只能有一個窗口管理器。

      l         .NET Remoting中服務(wù)器激活對象中的Sigleton對象,確保所有的客戶程序的請求都只有一個實(shí)例來處理。

      完整示例

      這是一個簡單的計(jì)數(shù)器例子,四個線程同時進(jìn)行計(jì)數(shù)。

       1using System;
       2using System.Threading;
       3
       4namespace SigletonPattern.SigletonCounter
       5{
       6    /// <summary>
       7    /// 功能:簡單計(jì)數(shù)器的單件模式
       8    /// 編寫:Terrylee
       9    /// 日期:2005年12月06日
      10    /// </summary>

      11    public class CountSigleton
      12    {
      13        ///存儲唯一的實(shí)例
      14        static CountSigleton uniCounter = new CountSigleton();  
      15   
      16        ///存儲計(jì)數(shù)值
      17        private int totNum = 0;  
      18   
      19        private CountSigleton() 
      20   
      21        
      22            ///線程延遲2000毫秒
      23            Thread.Sleep(2000);
      24        }
       
      25   
      26        static public CountSigleton Instance() 
      27   
      28        
      29   
      30            return uniCounter; 
      31   
      32        }
       
      33        
      34        ///計(jì)數(shù)加1
      35        public void Add()
      36        
      37            totNum ++;
      38        }
        
      39        
      40        ///獲得當(dāng)前計(jì)數(shù)值
      41        public int GetCounter()
      42        
      43            return totNum;
      44        }
       
      45
      46    }

      47}

      48

       

       1using System;
       2using System.Threading;
       3using System.Text;
       4
       5namespace SigletonPattern.SigletonCounter
       6{
       7    /// <summary>
       8    /// 功能:創(chuàng)建一個多線程計(jì)數(shù)的類
       9    /// 編寫:Terrylee
      10    /// 日期:2005年12月06日
      11    /// </summary>

      12    public class CountMutilThread
      13    {
      14        public CountMutilThread()
      15        {
      16            
      17        }

      18
      19        /// <summary>
      20        /// 線程工作
      21        /// </summary>

      22        public static void DoSomeWork()
      23        {
      24            ///構(gòu)造顯示字符串
      25            string results = "";
      26
      27            ///創(chuàng)建一個Sigleton實(shí)例
      28            CountSigleton MyCounter = CountSigleton.Instance();
      29
      30            ///循環(huán)調(diào)用四次
      31            for(int i=1;i<5;i++)
      32            {
      33                ///開始計(jì)數(shù)
      34                MyCounter.Add();
      35                
      36                results +="線程";
      37                results += Thread.CurrentThread.Name.ToString() + "——〉";
      38                results += "當(dāng)前的計(jì)數(shù):";
      39                results += MyCounter.GetCounter().ToString();
      40                results += "\n";
      41
      42                Console.WriteLine(results);
      43                
      44                ///清空顯示字符串
      45                results = "";
      46            }

      47        }

      48
      49        public void StartMain()
      50        {
      51
      52            Thread thread0 = Thread.CurrentThread; 
      53   
      54            thread0.Name = "Thread 0"
      55   
      56            Thread thread1 =new Thread(new ThreadStart(DoSomeWork)); 
      57   
      58            thread1.Name = "Thread 1"
      59   
      60            Thread thread2 =new Thread(new ThreadStart(DoSomeWork)); 
      61   
      62            thread2.Name = "Thread 2"
      63   
      64            Thread thread3 =new Thread(new ThreadStart(DoSomeWork)); 
      65   
      66            thread3.Name = "Thread 3"
      67   
      68            thread1.Start(); 
      69   
      70            thread2.Start(); 
      71   
      72            thread3.Start(); 
      73            
      74            ///線程0也只執(zhí)行和其他線程相同的工作
      75            DoSomeWork(); 
      76        }

      77    }

      78}

      79

       

       1using System;
       2using System.Text;
       3using System.Threading;
       4
       5namespace SigletonPattern.SigletonCounter
       6{
       7    /// <summary>
       8    /// 功能:實(shí)現(xiàn)多線程計(jì)數(shù)器的客戶端
       9    /// 編寫:Terrylee
      10    /// 日期:2005年12月06日
      11    /// </summary>

      12    public class CountClient
      13    {
      14        public static void Main(string[] args)
      15        {
      16       CountMutilThread cmt = new CountMutilThread();
      17
      18            cmt.StartMain();
      19
      20            Console.ReadLine();
      21        }

      22    }

      23}

      24

      總結(jié)

      Sigleton設(shè)計(jì)模式是一個非常有用的機(jī)制,可用于在面向?qū)ο蟮膽?yīng)用程序中提供單個訪問點(diǎn)。文中通過五種實(shí)現(xiàn)方式的比較和一個完整的示例,完成了對Sigleton模式的一個總結(jié)和探索。用一句廣告詞來概括Sigleton模式就是“簡約而不簡單”。

      _________________________________________________________________________________________________
      源碼下載:/Files/Terrylee/SigletonPattern.rar

      參考文獻(xiàn):

      C#計(jì)模式》,中國電力出版社

      使用 Microsoft .NET 的企業(yè)解決方案模式

      Implementing the Singleton Pattern in C#

      MSDNExploring the Singleton Design Pattern

      呂震宇C#設(shè)計(jì)模式(7)-Singleton Pattern

      C#的Singleton設(shè)計(jì)模式

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多