singleton模式是Gof提出的23中模式之一,也稱(chēng)為單例模式,那么簡(jiǎn)單說(shuō)一下,什么叫單例模式呢?
通常我們創(chuàng)建類(lèi)的對(duì)象是使用new Object(),然后就調(diào)用該對(duì)象里面的方法,那么當(dāng)我們多次使用new Object()的話(huà),會(huì)對(duì)系統(tǒng)資源造成一種浪費(fèi),當(dāng)然.net內(nèi)部已經(jīng)有垃圾回收機(jī)制可以處理這種浪費(fèi)。當(dāng)然我們并不會(huì)再程序里面多次使用new Object(),但是,作為一個(gè)類(lèi)的設(shè)計(jì)者,我們需要負(fù)什么責(zé)任,除了讓別的模塊可以調(diào)用使用之外,我們的設(shè)計(jì)還需要一種規(guī)范,這也是OO里面的規(guī)范,singleton模式在這里派上了用場(chǎng)。
singleton模式的意圖:確保一個(gè)類(lèi)只能擁有一個(gè)實(shí)例,并保證邏輯的正確性以及良好的效率,并提供一個(gè)該實(shí)例的全局訪(fǎng)問(wèn)點(diǎn)。
singleton模式類(lèi)型:?jiǎn)尉€(xiàn)程singleton,多線(xiàn)程singleton
singleton思路:要讓使用者只能使用一個(gè)實(shí)例的話(huà),那么必須繞過(guò)常規(guī)的公有缺省構(gòu)造器
singleton代碼:
1 public class singleton
2 {
3 private static singleton instance;
4 private singleton() { }
5 public static singleton Instance
6 {
7 get
8 {
9 if (instance == null)
10 {
11 instance = new singleton();
12 }
13 return instance;
14 }
15 }
16 }
17
第4行:利用私有構(gòu)造函數(shù)繞開(kāi)系統(tǒng)自帶的缺省公有構(gòu)造函數(shù),這樣就使類(lèi)的外部不可以直接使用new實(shí)例化對(duì)象
第5行:提供一個(gè)靜態(tài)的公有屬性,供類(lèi)外部調(diào)用
第9行:在這里可能存在BUG,當(dāng)有兩個(gè)線(xiàn)程同時(shí)操作公有屬性時(shí),常規(guī)的話(huà)應(yīng)該返回兩個(gè)一樣的實(shí)例,但是假如當(dāng)?shù)谝粋€(gè)實(shí)例還未來(lái)得及創(chuàng)建時(shí),第二個(gè)線(xiàn)程又訪(fǎng)問(wèn)了它,顯然也會(huì)執(zhí)行 new singleton()這個(gè)語(yǔ)句,那么這兩個(gè)對(duì)象的引用就不一樣了,可以使用object.ReferenceEquals測(cè)試一下對(duì)象的引用是否一樣。因此,給大家提供多線(xiàn)程方案,請(qǐng)看下面代碼
1 public class singletons
2 {
3 private static volatile singletons instances = null;
4 private static object lockHelper = new object();
5 private singletons() { }
6 public static singletons Instance
7 {
8 get
9 {
10 if(instances==null)
11 {
12 lock (lockHelper)
13 {
14 if(instances==null )
15 {
16 instances = new singletons();
17 }
18 }
19 }
20 return instances;
21 }
22 }
23 }
顯然看起來(lái)與單線(xiàn)程singleton差不多,多了volatile 修飾符,還有一個(gè)Object對(duì)象,接下來(lái)跟大家解釋使用這些其中的緣由
volatile 修飾符
假如我定義兩個(gè)變量和兩個(gè)屬性
1 int a;
2 volatile int b;
3 public int GetFirst
4 {
5 get { return a; }
6 }
7 public int GetSecond
8 {
9 get { return b; }
10 }
GetFirst會(huì)得到當(dāng)前線(xiàn)程中a的值,而多個(gè)線(xiàn)程就會(huì)有多個(gè)a的變量拷貝,而且這些拷貝之間可以互不相同,換句話(huà)說(shuō),另一個(gè)線(xiàn)程可能改變了它線(xiàn)程內(nèi)的a值,而這個(gè)值和當(dāng)前線(xiàn)程中的a值不相同,那么就造成線(xiàn)程沖突了。
那么再來(lái)看看b,因?yàn)?span style="color: #0000ff">volatile 修飾的變量不允許有不同于“主”內(nèi)存區(qū)域的變量拷貝,換句話(huà)說(shuō),一個(gè)變量經(jīng)volatile 修飾后在所有線(xiàn)程中都是同步的;任何線(xiàn)程改變了它的值,所以其他線(xiàn)程立即獲取到了相同的值,當(dāng)然加了volatile 修飾的變量存儲(chǔ)時(shí)會(huì)比一般變量消耗的資源要多一點(diǎn)。
Object對(duì)象鎖
對(duì)象鎖可以保證Lock里面的代碼只能同時(shí)讓一個(gè)線(xiàn)程執(zhí)行,所以確保了一個(gè)對(duì)象只存在一個(gè)實(shí)例。
同樣的需求可以有不同的方法實(shí)現(xiàn),以下是另外一種實(shí)現(xiàn)singleton模式的代碼,代碼更簡(jiǎn)單,不夠有缺陷,請(qǐng)看
1 public class singletonss
2 {
3 public static readonly singletonss Instance = new singletonss();
4 private singletonss() { }
5 }
首先定義一個(gè)靜態(tài)的只讀實(shí)例,當(dāng)然也需要私有構(gòu)造器繞過(guò)缺省構(gòu)造器,這樣子也可以保證多線(xiàn)程里也只誕生一個(gè)對(duì)象實(shí)例,因?yàn)?Net類(lèi)型初始化機(jī)制保證只有一個(gè)線(xiàn)程執(zhí)行了靜態(tài)構(gòu)造器。當(dāng)然這么少的代碼也可以實(shí)現(xiàn)singleton,但是靜態(tài)構(gòu)造器不支持參數(shù),也不能重構(gòu),因?yàn)樵?Net機(jī)制里面只允許一個(gè)類(lèi)擁有一個(gè)靜態(tài)構(gòu)造器而且是私有的,外部不能調(diào)用只能供系統(tǒng)調(diào)用,所以我們不能使用參數(shù)。
本文轉(zhuǎn)自:http://www.cnblogs.com/magicchaiy/archive/2010/12/02/1894826.html
其他鏈接:http://www.shnenglu.com/dyj057/archive/2005/09/20/346.html
posted on 2012-07-13 08:14
王海光 閱讀(464)
評(píng)論(0) 編輯 收藏 引用 所屬分類(lèi):
Design Pattern