免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

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

深入淺出單件模式(Sigleton Pattern

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

Terrylee,20051207

概述

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

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

意圖

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

模型圖

邏輯模型圖:

物理模型圖:

生活中的例子

美國(guó)總統(tǒng)的職位是Sigleton,美國(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)

 1
public 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)境下有可能得到Sigleton類(lèi)的多個(gè)實(shí)例。如果同時(shí)有兩個(gè)線程去判斷(instance == null),并且得到的結(jié)果為真,這時(shí)兩個(gè)線程都會(huì)創(chuàng)建類(lèi)Sigleton的實(shí)例,這樣就違背了Sigleton模式的原則。實(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)建的,因此類(lèi)可以使用附加功能(例如,對(duì)子類(lèi)進(jìn)行實(shí)例化),即使它可能引入不想要的依賴性。

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

2.安全的線程

 1
public 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)銷(xiāo),損失了性能。

3.雙重鎖定

 1
public 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)用程序很少需要這種類(lèi)型的實(shí)現(xiàn)。大多數(shù)情況下我們會(huì)用靜態(tài)初始化。這種方式仍然有很多缺點(diǎn):無(wú)法實(shí)現(xiàn)延遲初始化。

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

 1
public 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)生懷疑,這還是Sigleton模式嗎?在此實(shí)現(xiàn)中,將在第一次引用類(lèi)的任何成員時(shí)創(chuàng)建實(shí)例。公共語(yǔ)言運(yùn)行庫(kù)負(fù)責(zé)處理變量初始化。該類(lèi)標(biāo)記為 sealed 以阻止發(fā)生派生,而派生可能會(huì)增加實(shí)例。此外,變量標(biāo)記為 readonly,這意味著只能在靜態(tài)初始化期間(此處顯示的示例)或在類(lèi)構(gòu)造函數(shù)中分配變量。

該實(shí)現(xiàn)與前面的示例類(lèi)似,不同之處在于它依賴公共語(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ù)是私有的,因此不能在類(lèi)本身以外實(shí)例化 Singleton 類(lèi);因此,變量引用的是可以在系統(tǒng)中存在的唯一的實(shí)例。

由于 Singleton 實(shí)例被私有靜態(tài)成員變量引用,因此在類(lè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.延遲初始化

 1
public 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類(lèi)的一個(gè)靜態(tài)成員來(lái)完成,這樣就實(shí)現(xiàn)了延遲初始化,并具有很多的優(yōu)勢(shì),是值得推薦的一種實(shí)

現(xiàn)方式。

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

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

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

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

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

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

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

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

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

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

l         靈活性:因?yàn)轭?lèi)控制了實(shí)例化過(guò)程,所以類(lèi)可以更加靈活修改實(shí)例化過(guò)程

缺點(diǎn)

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

l          可能的開(kāi)發(fā)混淆:使用 singleton 對(duì)象(尤其在類(lèi)庫(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èi)。

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

適用性

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

l         當(dāng)這個(gè)唯一實(shí)例應(yīng)該是通過(guò)子類(lèi)化可擴(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ù)。

 1
using System;
 2
using System.Threading;
 3

 4
namespace SigletonPattern.SigletonCounter
 5
{
 6
    
/// <summary>
 7
    
/// 功能:簡(jiǎn)單計(jì)數(shù)器的單件模式
 8
    
/// 編寫(xiě):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

 

 1
using System;
 2
using System.Threading;
 3
using System.Text;
 4

 5
namespace SigletonPattern.SigletonCounter
 6
{
 7
    
/// <summary>
 8
    
/// 功能:創(chuàng)建一個(gè)多線程計(jì)數(shù)的類(lèi)
 9
    
/// 編寫(xiě):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

 

 1
using System;
 2
using System.Text;
 3
using System.Threading;
 4

 5
namespace SigletonPattern.SigletonCounter
 6
{
 7
    
/// <summary>
 8
    
/// 功能:實(shí)現(xiàn)多線程計(jì)數(shù)器的客戶端
 9
    
/// 編寫(xiě):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ì)模式是一個(gè)非常有用的機(jī)制,可用于在面向?qū)ο蟮膽?yīng)用程序中提供單個(gè)訪問(wèn)點(diǎn)。文中通過(guò)五種實(shí)現(xiàn)方式的比較和一個(gè)完整的示例,完成了對(duì)Sigleton模式的一個(gè)總結(jié)和探索。用一句廣告詞來(lái)概括Sigleton模式就是“簡(jiǎn)約而不簡(jiǎn)單”。

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

參考文獻(xiàn):

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

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

Implementing the Singleton Pattern in C#

MSDNExploring the Singleton Design Pattern

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

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

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Singleton模式 - 鋼鐵人生 - 博客園
Java單例模式深入詳解
【設(shè)計(jì)模式】5. 單例模式(以及多線程、無(wú)序?qū)懭?、volatile對(duì)單例的影響)
《Head First設(shè)計(jì)模式》閱讀筆記.第五章
C#設(shè)計(jì)模式系列:?jiǎn)渭J剑⊿ingleton)
設(shè)計(jì)模式——單例模式(Singleton)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服