C#設(shè)計模式之單例模式
單例模式也是創(chuàng)建型模式的一種,也是23種設(shè)計模式中比較簡單的一種。見名思意,在整個軟件系統(tǒng)中,只有某個類型的一個對象,并且訪問他的地方也只有一個,也就是只有一個全局對象訪問點,這個實例或?qū)ο蟊凰惺菓?yīng)用程序所共享;很多可以使用到這樣的功能模塊:比如數(shù)據(jù)庫連接池對象、打印機對象,因為整個系統(tǒng)中,數(shù)據(jù)庫的連接只在一個地方連接,打印機在整個系統(tǒng)中也只有一個。這種情況下,單例模式就很大的減少了一個內(nèi)存的開銷,因為對象的創(chuàng)建是比較消耗內(nèi)存的,同時因為系統(tǒng)中只有一個實例,比較容易控制,省去了對象創(chuàng)建的過程,更快的進行一個響應(yīng),但是在使用單例模式時,由于只有一個實例,所有的線程都可以去使用這個實例,那么不能保證線程的一個安全性,如果要想保證線程的安全性,我們需要使用其他的一些輔助措施。所以對于線程安全的對象我們最好不要使用單例模式,否則可能會降低系統(tǒng)的效率。單例模式只需要一個類就可以實現(xiàn),自己關(guān)聯(lián)自己,那么如何實現(xiàn)呢?我們只需要將構(gòu)造方法定義成私有的,這樣用戶就不能自己去創(chuàng)建這個對象了,然后通過一個靜態(tài)方法和靜態(tài)變量來存放類的唯一的一個實例。
示例:
創(chuàng)建單例類:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 單例模式
{
public class Singleton
{
/// <summary>
/// 1.定義一個私有的構(gòu)造函數(shù),在類的外部不能被調(diào)用
/// </summary>
private Singleton()
{
Console.WriteLine("我被創(chuàng)建了!");
}
// 2.創(chuàng)建該類的一個靜態(tài)變量
private stati
c Singleton Instance;
// 3.創(chuàng)建返回值為該類型的一個靜態(tài)方法 (此方法對外公開)
public static Singleton CreateInstance()
{
if (Instance == null)
{
Instance = new Singleton();
}
return Instance;
}
}
}主程序調(diào)用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 單例模式
{
class Program
{
static void Main(string[] args)
{
Singleton s1 = Singleton.CreateInstance();
Singleton s2 = Singleton.CreateInstance();
Console.ReadKey();
}
}
}運行結(jié)果:

從最后的結(jié)果中可以看出,實例只被創(chuàng)建了一次。
在來看看下面的例子:
for (int i = 0; i < 10; i++)
{
// 執(zhí)行委托的異步調(diào)用
new Action(() =>
{
Singleton singleton = Singleton.CreateInstance();
}).BeginInvoke(null,null);
}結(jié)果:

從上面的截圖中看出構(gòu)造函數(shù)被執(zhí)行了三次。單例模式不是只會構(gòu)造一次嗎?這里為什么執(zhí)行了三次呢?因為這里是多線程并發(fā)的,10個任務(wù)是同時開始的,可能對象不為null的時候有多個線程進入了,所以會執(zhí)行多次。要解決這種問題,可以使用加鎖。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 單例模式
{
public class Singleton
{
/// <summary>
/// 1.定義一個私有的構(gòu)造函數(shù),在類的外部不能被調(diào)用
/// </summary>
private Singleton()
{
Console.WriteLine("我被創(chuàng)建了!");
}
// 2.創(chuàng)建該類的一個靜態(tài)變量
private static Singleton Instance;
// 創(chuàng)建鎖
private static object Singleton_Lock = new object();
// 3.創(chuàng)建返回值為該類型的一個靜態(tài)方法 (此方法對外公開)
public static Singleton CreateInstance()
{
lock(Singleton_Lock) // 保證任意時刻只有一個線程才能進入判斷
{
if (Instance == null)
{
Instance = new Singleton();
}
}
return Instance;
}
}
}再次運行程序查看結(jié)果:

這時只會構(gòu)造一個對象了。
在來看看懶漢式的單例模式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 單例模式
{
public class SingletonSecond
{
private SingletonSecond()
{
Console.WriteLine("我被創(chuàng)建了!");
}
private static SingletonSecond Instance = null;
/// <summary>
/// 靜態(tài)構(gòu)造函數(shù):由CLR保證在第一次使用這個類之前,調(diào)用而且只調(diào)用一次
/// </summary>
static SingletonSecond()
{
Instance = new SingletonSecond();
}
public static SingletonSecond CreateInstance()
{
return Instance;
}
}
}在來看看第三種寫法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 單例模式
{
public class SingletonThird
{
private SingletonThird()
{
Console.WriteLine("我被創(chuàng)建了!");
}
/// <summary>
/// 靜態(tài)變量:會在類型第一次使用的時候初始化,而且只初始化一次
/// </summary>
private static SingletonThird Instance = new SingletonThird();
public static SingletonThird CreateInstance()
{
return Instance;
}
}
}代碼下載地址:點擊下載
到此這篇關(guān)于C#設(shè)計模式之單例模式的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中StringBuilder用法以及和String的區(qū)別分析
當(dāng)我們在初學(xué)使用C#時,常常會不知道該用StringBuilder合適還是用String高效,下面是我在學(xué)習(xí)當(dāng)中對StringBuilder和String的區(qū)別總結(jié),分享給大家。2013-03-03

