久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Singleton模式 - 鋼鐵人生 - 博客園

 Alex847 2009-10-14

概述

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

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

 一眼看去,Singleton似乎有些像全局對(duì)象,。但是實(shí)際上,,并不能用全局對(duì)象代替Singleton模式,這是因?yàn)椋浩湟?,大量使用全局?duì)象會(huì)使得程序質(zhì)量降低,,而且有些編程語(yǔ)言例如C#,根本就不支持全局變量,。其二,,全局對(duì)象的方法并不能阻止人們將一個(gè)類實(shí)例化多次:除了類的全局實(shí)例外,開(kāi)發(fā)人員仍然可以通過(guò)類的構(gòu)造函數(shù)創(chuàng)建類的多個(gè)局部實(shí)例,。而Singleton模式則通過(guò)從根本上控制類的創(chuàng)建,,將"保證只有一個(gè)實(shí)例"這個(gè)任務(wù)交給了類本身,,開(kāi)發(fā)人員不可能再有其它途徑得到類的多個(gè)實(shí)例。這一點(diǎn)是全局對(duì)象方法與Singleton模式的根本區(qū)別,。
  Singleton模式的實(shí)現(xiàn)
  Singleton模式的實(shí)現(xiàn)基于兩個(gè)要點(diǎn):
  
  1)不直接用類的構(gòu)造函數(shù),,而另外提供一個(gè)Public的靜態(tài)方法來(lái)構(gòu)造類的實(shí)例。通常這個(gè)方法取名為Instance,。Public保證了它的全局可見(jiàn)性,,靜態(tài)方法保證了不會(huì)創(chuàng)建出多余的實(shí)例。
  
  2)將類的構(gòu)造函數(shù)設(shè)為Private,,即將構(gòu)造函數(shù)"隱藏"起來(lái),,任何企圖使用構(gòu)造函數(shù)創(chuàng)建實(shí)例的方法都將報(bào)錯(cuò)。這樣就阻止了開(kāi)發(fā)人員繞過(guò)上面的Instance方法直接創(chuàng)建類的實(shí)例,。下面給出一個(gè)實(shí)際在用的時(shí)候的例子,緊接著再討論為什么這么做.
通過(guò)以上兩點(diǎn)就可以完全控制類的創(chuàng)建:無(wú)論有多少地方需要用到這個(gè)類,,它們?cè)L問(wèn)的都是類的唯一生成的那個(gè)實(shí)例。

using System; 
  
class SingletonDemo 
  

private static SingletonDemo theSingleton = null
   
private SingletonDemo() {} 
   
public static SingletonDemo Instance() 
   
if (null == theSingleton) 
   

   theSingleton 
= new SingletonDemo(); 
   }
 
   
return theSingleton; 
   }
 
   
static void Main(string[] args) 
   
{ SingletonDemo s1 = SingletonDemo.Instance(); 
   SingletonDemo s2 
= SingletonDemo.Instance(); 
   
if (s1.Equals(s2)) 
   
{ Console.WriteLine("see, only one instance!"); 
   }
 
   }
 
  }
 


意圖

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

模型圖

邏輯模型圖:

物理模型圖:

生活中的例子

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

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

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

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

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

l         直到對(duì)象要求產(chǎn)生一個(gè)實(shí)例才執(zhí)行實(shí)例化,;這種方法稱為“惰性實(shí)例化”。惰性實(shí)例化避免了在應(yīng)用程序啟動(dòng)時(shí)實(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)對(duì)于線程來(lái)說(shuō)是安全的,。我們首先創(chuàng)建了一個(gè)進(jìn)程輔助對(duì)象,線程在進(jìn)入時(shí)先對(duì)輔助對(duì)象加鎖然后再檢測(cè)對(duì)象是否被創(chuàng)建,,這樣可以確保只有一個(gè)實(shí)例被創(chuàng)建,,因?yàn)樵谕粋€(gè)時(shí)刻加了鎖的那部分程序只有一個(gè)線程可以進(jìn)入。這種情況下,,對(duì)象實(shí)例由最先進(jìn)入的那個(gè)線程創(chuàng)建,,后來(lái)的線程在進(jìn)入時(shí)(instence == null)為假,不會(huì)再去創(chuàng)建對(duì)象實(shí)例了,。但是這種實(shí)現(xiàn)方式增加了額外的開(kāi)銷,,損失了性能。

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

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

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

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

這種方法唯一的潛在缺點(diǎn)是,您對(duì)實(shí)例化機(jī)制的控制權(quán)較少,。在 Design Patterns形式中,,您能夠在實(shí)例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)。由于在此解決方案中由 .NET Framework 負(fù)責(zé)執(zhí)行初始化,,因此您沒(méi)有這些選項(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類的一個(gè)靜態(tài)成員來(lái)完成,這樣就實(shí)現(xiàn)了延遲初始化,,并具有很多的優(yōu)勢(shì),,是值得推薦的一種實(shí)

現(xiàn)方式。

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

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

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

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

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

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

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

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

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

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

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

缺點(diǎn)

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

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

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

適用性

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

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

應(yīng)用場(chǎng)景

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

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

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

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

完整示例

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

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

11    public class CountSigleton
12    {
13        ///存儲(chǔ)唯一的實(shí)例
14        static CountSigleton uniCounter = new CountSigleton();  
15   
16        ///存儲(chǔ)計(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)建一個(gè)多線程計(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)建一個(gè)Sigleton實(shí)例
28            CountSigleton MyCounter = CountSigleton.Instance();
29
30            ///循環(huán)調(diào)用四次
31            for(int i=1;i<5;i++)
32            {
33                ///開(kāi)始計(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é)

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

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多