天天看點

java之單例設計模式那麼如何確定對象的唯一性? 那麼如何實作?代碼實作:代碼分析:

單例模式解決的問題就是可以確定一個類在記憶體中的對象唯一性。

它可以實作資料共享,比如A程式需要用到一個配置檔案,B程式也要用到一個配置檔案,現在有個需求:A程式如果修改了這個配置檔案,B程式需要知道更新過後的這個配置檔案。這時候就要使用單例模式來確定配置檔案的唯一性。

那麼如何確定對象的唯一性?

1 不允許其他程式用new來建立該類的對象。

2 在該類中建立一個本來執行個體。

3 對外提供一個方法讓其他程式可以擷取對象。

那麼如何實作?

1 私有化該類的構造函數。這樣類外部無法通路構造函數進行建立對象。

2 通過new在本類中建立一個本類對象。

3 定義一個公有的方法,将建立的對象傳回,提供給外部使用。

代碼實作:

class Single
{
	static Single sg = new Single();
	
	private Single()
	{
		
	}
	 //外部不能建立Single對象,還要擷取這個對象,那麼擷取的函數必須是static,
	 //這樣可以通過類名調用了。
	public static Single getInstance() 
	{
		return sg; 
	}
//--------------------------------------------------	
	private int num;  //單例裡面的資料
	public void SetNum(int num)
	{
		this.num = num;
	}
	public int GetNum()
	{
		return this.num;
	}
//--------------------------------------------------	
}

class SingleDemo
{
	public static void main(String[] args)
	{
		Single s = Single.getInstance(); //①
		
		Single s = Single.sg; //②  
		
	
	}
}
           

代碼分析:

1 既然②也可以通路單例對象,那麼為什麼還要用①這種形式來通路呢?

因為通過②這種方式通路單例,不如形式①通過函數通路可控,①的可控展現在可以在函數内部對sg進行相關處理,(比如取不到單例就傳回null)

說白了①方式是函數調用,函數内部可以寫更多的代碼來控制着單例。是以一般推薦①方式來通路。

2 為了避免不安全的調用,我們習慣将單例改成private權限,即

static Single sg = new Single() ==>  private static Single sg = new Single()

接下來我們進一步修改:

class Single
{
	private static Single sg = new Single(); //加了一個private限制 ③
	
	private Single()
	{
		
	}
	
	public static Single getInstance() 
	{
		return sg; 
	}
}

class SingleDemo
{
	public static void main(String[] args)
	{
		Single s1 = Single.getInstance(); 
		Single s2 = Single.getInstance(); 
		System.out.println(s1 == s2);  //結果為true
	}
}
           

我們看到上面代碼的③:

如果我們延遲加載,在調用getInstance方法的時候再建立對象,我們需要修改一下代碼如下:

//但是這種方式存在隐患,在多線程裡面使用有時候會無法保證單例的唯一性。
class Single
{
	//類加載進來,沒有對象,隻有調用了getInstace方法時,才會建立對象。
	private static Single sg = null;  
	
	private Single()
	{
		
	}
	
	public static Single getInstance() 
	{
		if(sg == null)
			a = new Single(); 
		return sg; 
	}
}
           

注意:但是這種方式存在安全隐患,在多線程裡面使用時候會無法保證單例的唯一性。