1.目的
控制實例的個數,類設計者應該保證只有一個實例,不能將此責任【只有一個實例】強制交給類使用者。
2.整體實現
1.單線程單例模式的實現。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LearnDesignPattern
{
public class Singleton
{
private Singleton() { }//構造函數私有化,使得用戶無法通過new關鍵字創建對象
private static Singleton instance;
public static Singleton Instance
{
get
{//懶加載模式,用戶也可以每次獲取的時候,都new,但是這樣不推薦
//首先判斷,如果爲第一次使用,則進行new
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
//注意【1】,C#的單例模式一般使用屬性來獲取Instance
//而在Java,中一般使用public static Singleton getInstance()的方法,這點不同
//注意【2】,爲什麼要使用Static關鍵字呢,我們知道Static的關鍵字的作用是
//可以直接通過類名來進行調用,這樣就保證了,需要先有類的實例才能獲取
//非static屬性的情況
}
}
2.多線程單例模式實現:
//如果兩個線程同時判斷instance是不是爲空,當instance==null的時候
//兩個線程就同時創建出來實例,這樣就存在了兩個實例了
public class Singleton
{
private Singleton() { }
//volatile:被volatile修飾的變量的值,將不會被本地線程換緩存
//所有對該變量的讀寫都是直接操作共享內存,從而確保多個線程能
//正確的處理該變量
private static volatile Singleton instance;
//添加線程鎖,確保只有一個線程可以訪問該範圍的代碼,其他線程等待
private static object objectLock = new object();
public static Singleton Instance
{
//double check雙重檢查機制
get
{
if (instance == null)
{
lock (objectLock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
3.經典的多線程單例模式寫法。
//【使用靜態構造器】
//1.靜態構造函數既沒有訪問修飾符,也沒有參數
//2.在創建第一個實例或引用任何靜態成員之前,將自動調用靜態構造函數來初始化類
//3.無法直接調用靜態構造函數
//4.在程序中,用戶無法控制何時執行靜態構造函數
//【保證1】保證使用類實例或者靜態成員之前初始化
//【保證2】懶加載,只有在第一次使用,才調用靜態構造器
//【保證3】.net框架會自動爲多線程加鎖
public static readonly Singleton Instance = new Singleton();
private Singleton() { }
//【弊端】不支持參數化Singleton,因爲傳參必須使用方法來進行!!!GetInstance(object a,object b){}
4.參數化Singleton
//參數化Singleton
private Singleton(int a,int b)
{
this.A = a;//A、B均爲靜態屬性
this.B = b;//A、B均爲靜態屬性
}
public static Singleton GetInstance(int x, int y)
{
if (instance == null)
{
instance= new Singleton(x, y);
}
//可修改單例模式!就相當於修改當前單例的屬性,並不會重新創建新的實例
else
{
instance.A = x;//A、B均爲靜態屬性
instance.B = y;//A、B均爲靜態屬性
}
return instance;
}
3.思考
1.實例的個數可以兩個麼?三個......多個。使用時,一次創建多個,放在池子中,使用的時候去取。
2.如何將new構造器放到其他類中,實現局部使用一個對象的實例。
3.將new進行屏蔽,然後通過其他方法來實現new的效果【不僅僅是單例】。