設計模式-單例模式(一)

單例模式(一)

特別聲明:由於本人也爲初學者,如果以下講解的有問題,望大家可以批評指正,歡迎一起來討論。

定義:確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,它提供全局訪問的方法。

由定義可以看出,單例模式必須要滿足如下幾點:

(1)系統中一個類只能有一個實例;

(2)自行實例化;

(3)提供全局訪問的方法。

既然單例模式符合上邊三種規則,那在實現這三種規則時,具體是咱們實現的呢?首先看一下以下最簡單的單例模式的實現:

public class BaseSingle {	
	private static BaseSingle instance=null;	
	private BaseSingle(){		
	}	
	public static BaseSingle getInstance() {
		if(instance==null){
			instance=new BaseSingle();
		}
		return instance;
	}		
}
看到以上代碼,大家也許會有這幾個問題:

(1)代碼中的成員變量爲什麼要聲明爲靜態的?

(2)類的構造函數爲什麼要聲明爲私有的?

(3)得到實例的getInstance方法爲什麼要聲明爲靜態的呢?

想弄清這幾個問題,我想應該從單例模式的特點開始思考:

(1)系統中一個類只能有一個實例:java中,一般我們在創建類的實例時,都是在類的外部new出對象,如:如 A a=new A();這樣,我們就給類A創建了一個實例a,可是,如果在寫程序時,我們可以在類的外部任意調用其構造函數進行類的實例化,那還怎麼能滿足系統中一個類只能有一個實例這個特點呢?so,爲了禁止客戶端自己在類外部進行實例化,只能讓客戶端無法訪問其類的構造函數,so,將類的構造函數聲明爲私有成員,及類的實例只能在類中進行創建。

寫到這我想大家會又有問題了,我們在訪問一個類中的成員變量或者方法時,都是先得到這個類的實例,然後通過這個類的實例來訪問其中類的成員變量或者方法,可是,你爲了保證客戶端不能隨意的創建對象,將其構造函數進行了私有化,那外部想要訪問這個類中的成員變量或其中的方法,該怎麼訪問呢?既然不能new出對象來訪問了,我想就只能另找途徑了。想到這裏,大家應該會想到java中訪問類中的成員變量或方法常用有以下兩種方式:

1)通過new出一個對象,然後通過對象進行其成員變量或成員方法的訪問(此方法已在前述中被證明不可行);

2)通過類名直接訪問其靜態方法或靜態變量,以達到訪問該類中成員變量或其方法的目的..

注意:這兩種方式雖然表面都可以訪問類中的變量或者類中的函數,可其實現原理,內存分配是完全不一樣的。

既然第一種方法不行,那就只能想,不用創建對象,就可以訪問類中的變量或函數,那這自然的就讓我們想到使用類名加靜態方法或靜態變量訪問其成員了,再加其前邊我們將類的構造函數聲明爲私有成員,及只能在類的內部進行類的實例化,so,我們只能在類的內部聲明一個靜態的類的對象等待我們去訪問,於是static BaseSingle instance=null便自然而然地出現在我們面前,可是爲了實現對類內部成員變量的保護,我們一般都講類中的變量變爲私有的,可是,變成私有之後,我們又該怎麼取訪問呢?沒錯,只能通過聲明一個公有的方法,通過該方法的返回值訪問該變量,可是,該方法必須保證可以在客戶端不創建類的對象的情況下就可以訪問到,於是,我們自然地也想到將其聲明爲靜態的公有的方法,通過該方法將類中的類實例返回,於是getInstance()爲何要聲明爲靜態公有的方法,以及方法中爲何加上if語句判斷,到這就已經清楚了。到這也滿足了單例模式定義中的第二個特點,自行實例化 。

(2)提供全局的方法,static修飾的靜態變量或方法是在加載類時進行創建的,整個過程中只初始化一次,通過全局只存在一個的變量進行對應的方法訪問,於是保證了提供全局方法的特性。

至此,將上述簡單的單例模式的代碼實現進行了講解。

可是,再仔細想一下,代碼這樣寫的話,如果只是一個用戶訪問,我們可以保證其單例,當多線程併發訪問時,是不是也能保證其單例性呢?大家可以先思考一下,然後帶着問題看即將發表的 單例模式(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章