天天看點

實作單例模式C#版本

對于單例模式先來一個C#版本的初級不能用的版本:

版本一不可行方法:

public class Singleton
{
	private Singleton()
	{}
	private static Singleton instance = null;
	
	public static Singleton getInstance()
	{
		if(instance == null)
			instance = new Singleton();
		
		return instance;
	}
}
           

  之是以說這是一個不能用的初級版本,因為它僅僅能用在單線程的情況下。在多線程并發的情況下是不能保持單例的。

這裡的不安全的地方是,多個線程同時對instance判斷都為null,然後都new一個執行個體,是以要在判instance為null的那段代碼加互斥鎖。

版本二可行低效方法:

public class Singleton
{
	private Singleton()
	{}
	private static Singleton instance = null;
	private static readonly object syncobj = new object();
	
	public static Singleton getInstance()
	{
		lock(syncobj)
		{
			if(instance == null)
				instance = new Singleton();
		}
		
		return instance;
	}
}
           

  但是這種互斥鎖是很消耗操作的,在沒有必要的時候,盡量少做互斥鎖。

是以做一個輕微的調整:

public class Singleton
{
	private Singleton()
	{}
	private static Singleton instance = null;
	private static readonly object syncobj = new object();
	
	public static Singleton getInstance()
	{
		if(instance == null)
		{
			lock(syncobj)
			{
				instance = new Singleton();
			}
		}
		return instance;
	}
}
           

  忽然發現這同樣是不能多線程的,是以要在加一層對instance的判斷null。

版本三可行方法:

public class Singleton
{
	private Singleton()
	{}
	private static Singleton instance = null;
	private static readonly object syncobj = new object();
	
	public static Singleton getInstance()
	{
		if(instance == null)
		{
			lock(syncobj)
			{
				if(instace == null)
				{
					instance = new Singleton();
				}
			}
		}
		return instance;
	}
}
           

  這樣就能夠支援多線程了,是一種可行的方法。

版本四推薦的版本:

public class Singleton
{
	private Singleton()
	{}
	private static Singleton instance = null;
	
	//靜态構造函數,對靜态成員變量初始化
	static Singleton()
	{
		instance = new Singleton();
	}
	public static Singleton getInstance()
	{
		return instance;
	}
}
           

下面對靜态構造函數做一個科普:

靜态構造函數用來初始化靜态變量,這個構造函數是屬于類的,而不是屬于哪個執行個體的。

就是說這個構造函數隻會被執行一次。也就是在建立第一個執行個體或引用任何靜态成員之前,由.NET自動調用。

靜态構造函數的特點:

1.靜态構造函數既沒有通路修飾符,也沒有參數。

2.在建立第一個執行個體或引用任何靜态成員之前,将自動調用靜态構造函數來初始化類,也就是無法直接調用靜态構造函數,也無法控制什麼時候執行靜态構造函數。

3.一個類隻能有一個靜态構造函數,最多隻能運作一次。

4.靜态構造函數不可以被繼承。

5.如果沒有靜态構造函數,而類中的靜态成員有初始值,那麼編譯器會自動生成預設的靜态構造函數。

從這裡可以看出靜态構造函數的調用時機不是由程式員掌控的,而是當.NET運作時發現第一次使用一個類型的時候自動調用該類型的靜态構造函數。

但是這種方法會過早的穿件執行個體,進而降低了記憶體的使用效率。

版本五更進階的版本:

現在想做的就是不要一碰到Singleton就申請一個靜态執行個體,要等到我調用getInstance的時候才申請執行個體空間。是以做一個内部類

public class Singleton
{
	private Singleton(){}
	
	public static Singleton getInstance()
	{
		return Nested.instance;
	}
	
	//外部類隻可以通路内部類的public和interal權限的字段、方法、屬性
	//嵌套類可以通路外部類的方法、屬性、字段而不受通路修飾符的限制
	class Nested
	{
		static Nested()
		{
			instance = new Singleton();
		}
		internal static Singleton instance = null;
	}
}
           

  

轉載于:https://www.cnblogs.com/stemon/p/4748247.html

c#