要求:一個(gè)類只有一個(gè)實(shí)例,并且提供了一個(gè)全局的訪問(wèn)點(diǎn),。注意:客戶端在調(diào)用一個(gè)類的時(shí)候,,不會(huì)考慮這個(gè)類是否只能有一個(gè)實(shí)例等問(wèn)題的,所以這是設(shè)計(jì)者的問(wèn)題,。
實(shí)現(xiàn):
實(shí)現(xiàn)1
public sealed class Singleton
{
private int count = 0;
//to make sure that all the instance of the class Singleton share the variable instance
static Singleton instance = null;
//private constructor to make sure that the client can't create the instance of the class singleton by calling the constructor
Singleton()
{
count++;
}
//the property Instance to provide an unique access point to get the unique instance of the class Singleton
public static Singleton Instance
{
get
{
if( instance == null )
{
instance = new Singleton();
}
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
缺點(diǎn):
對(duì)于線程來(lái)說(shuō)并不安全,因?yàn)樵诙嗑€程的環(huán)境下有可能得到Singleton類的多個(gè)實(shí)例.當(dāng)兩個(gè)線程都在判斷時(shí),因?yàn)閮?nèi)存模型并不能保證對(duì)象實(shí)例在第二個(gè)線程創(chuàng)建之前被發(fā)現(xiàn).
優(yōu)點(diǎn):
由于實(shí)例是在Instance屬性方法內(nèi)部創(chuàng)建的,因此類阿寬衣使用附加功能,因此類可以使用附加功能,比如對(duì)其他成員進(jìn)行初始化等
直到對(duì)象要求產(chǎn)生一個(gè)實(shí)例才執(zhí)行實(shí)例化,這種方法稱為"情性實(shí)例化",情性實(shí)例化避免了在應(yīng)用程序啟動(dòng)時(shí)實(shí)例化不必要的
singleton.
實(shí)現(xiàn)2:
public sealed class Singleton_Thread
{
static Singleton_Thread instance = null;
static readonly object padlock = new object();
static int count = 0;
Singleton_Thread()
{
count++;
}
public static Singleton_Thread Instance
{
get
{
//using the lock to make sure that at the same time only one thread can get into the block int the {}
lock(padlock)
{
if(instance == null)
{
instance = new Singleton_Thread();
}
return instance;
}
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
優(yōu)點(diǎn): 用lock講創(chuàng)建實(shí)例的代碼同一時(shí)刻只能被一個(gè)線程訪問(wèn),實(shí)現(xiàn)了線程安全,但是每次創(chuàng)建都要加鎖則增加了額外的開銷
實(shí)現(xiàn)3:使用雙鎖
public sealed class Singleton_DoubleLock
{
static Singleton_DoubleLock instance = null;
static int count = 0;
static readonly object padlock = new object();
Singleton_DoubleLock()
{
count++;
}
public static Singleton_DoubleLock Instance
{
get
{
if( instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton_DoubleLock();
}
}
}
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
優(yōu)點(diǎn):解決線程并發(fā),同時(shí)避免每個(gè)Instance屬性的調(diào)用都出現(xiàn)獨(dú)占鎖定.
并且將實(shí)例化延遲到第一次訪問(wèn)對(duì)象時(shí)發(fā)生
缺點(diǎn):不能實(shí)現(xiàn)延遲初始化
實(shí)現(xiàn)4:使用靜態(tài)構(gòu)造函數(shù)
public sealed class Singleton_Static
{
//static表明是在靜態(tài)初始化的時(shí)候被初始化.這個(gè)初始化操作由公用語(yǔ)言運(yùn)行庫(kù)完成
static readonly Singleton_Static instance;
static int count;
static Singleton_Static()
{
instance = new Singleton_Static();
count++;
}
Singleton_Static()
{
}
public static Singleton_Static Instance
{
get
{
return instance;
}
}
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
和上面的區(qū)別: 由CLR實(shí)現(xiàn)變量初始化
實(shí)現(xiàn)5:延遲初始化
public sealed class Singleton_Initil
{
static int count;
Singleton_Initil()
{
count++;
}
public static Singleton_Initil Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton_Initil instance = new Singleton_Initil();
};
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
};
應(yīng)用例子:
簡(jiǎn)單計(jì)數(shù)器,四個(gè)線程同時(shí)進(jìn)行計(jì)數(shù).
//實(shí)現(xiàn)一個(gè)單個(gè)計(jì)數(shù)器,singleton設(shè)計(jì)模式,所以只有一個(gè)計(jì)數(shù)器供四個(gè)線程使用.
public class CountSingleton
{
static CountSingleton uniCounter = new CountSingleton();
private int totNum = 0;
private CountSingleton()
{
Thread.Sleep(2000);
}
public static CountSingleton Instance()
{
return uniCounter;
}
public void Add()
{
totNum++;
}
public int GetCounter()
{
return totNum;
}
};
public class CountMutiThread
{
public CountMutiThread()
{
}
//每個(gè)線程執(zhí)行的操作就是進(jìn)行計(jì)數(shù),并輸出當(dāng)前的計(jì)數(shù)值
public static void DoSomeWork()
{
string results = "";
CountSingleton MyCounter = CountSingleton.Instance();
for(int i = 1; i < 5; i++ )
{
MyCounter.Add();
results += "線程";
results += Thread.CurrentThread.Name.ToString() + "--> ";
results += "當(dāng)前的計(jì)數(shù)";
results += MyCounter.GetCounter().ToString();
results += "\n";
Console.WriteLine(results);
results = "";
}
}
//創(chuàng)建四個(gè)線程并開始運(yùn)行
public void StartMain()
{
Thread thread0 = Thread.CurrentThread;
thread0.Name = "Thread 0";
Thread thread1 = new Thread(new ThreadStart(DoSomeWork));
thread1.Name = "Thread 1";
Thread thread2 = new Thread(new ThreadStart(DoSomeWork));
thread2.Name = "Thread 2";
Thread thread3 = new Thread(new ThreadStart(DoSomeWork));
thread3.Name = "Thread 3";
thread1.Start();
thread2.Start();
DoSomeWork();
thread3.Start();
}
};
class CountClient
{
static void Main(string[] args)
{
CountMutiThread cmt = new CountMutiThread();
cmt.StartMain();
Console.ReadLine();
}
}