java設計模式-----單例

 

單例模式應該是23種設計模式中最簡單的一種模式。它包含如下幾個要素  java

  1. 1私有的構造方法 
  2. 2指向本身實例的私有靜態引用 
  3. 3以本身實例爲返回值的靜態的公有的方法 


單例模式根據實例化對象的不一樣時間分爲餓漢和懶漢模式(其中還有一種登記式單例);
餓漢式單例在類被加載時候,實例化一個對象;而懶漢式在調用取得實例方法的時候纔會實例化對象 設計模式

單例有以下的優勢: 性能

在內存中只有一個對象。 spa

避免頻繁的建立銷燬對象。 設計

避免對共享資源的多重佔用。 code


public class Singleton1
{
	private static Singleton1 instance = new Singleton1();
	
	private Singleton1()
	{
		
	}
	
	public static Singleton1 getInstance()
	{
		return instance;
	}
}

在類第一次加載實例化一個實例,因此在使用時,花銷的時間比較少,比較快。 對象


餓漢式單例: 內存

public class Singleton
{
	private static Singleton instance = null;

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

該單例方式,只有在第一次調用getInstance()時纔會初始化一個實例,因此在第一次使用時會花銷必定的時間,同時須要同步,一樣會花銷必定的時間,這樣性能上會比第一種要差點,下面咱們會一一的驗證。 資源


首先咱們驗證一下是否經過單例提供的方法產生的實例是否是就是一個實例? get

Singleton1 instance1 = Singleton1.getInstance();
		instance1.setId("name");
		Singleton1 instance2 = Singleton1.getInstance();
		System.out.println(instance2.getId());


咱們經過getInstance()獲取實例,在第一個實例中設置了一個屬性值,在獲取一個實例,輸出他的id的值,

name

咱們並無設置第二個實例屬性值,可是他的id值已經被設置爲name,這一點說明咱們得到是同一個實例。


這裏有一個須要注意的問題,經過反射每次都能得到類的新的實例,因此若是你想使用單例,就不要使用反射建立類的實例對象。

經過下面的例子咱們能夠驗證一下

Singleton1 instance1 = Singleton1.getInstance();
		instance1.setId("name");
		Singleton1 instance2 = Singleton1.getInstance();
		System.out.println(instance2.getId());
		
		Class c = Class.forName(Singleton1.class.getName());
		Constructor ct = c.getDeclaredConstructor();
		ct.setAccessible(true);
		Singleton1 instance3 = (Singleton1)ct.newInstance();
		System.out.println(instance3.getId());

咱們能夠試想下結果應該是什麼(上面咱們說明)

name
null

 

上面咱們還提到兩種單例的性能問題,下面咱們在用例子說明一下:

//餓漢
		Long startTime1 = System.currentTimeMillis();
		for(int i = 0 ;i<100000000;i++)
		{
			Singleton1 instance = Singleton1.getInstance();
		}
		Long endTime1 = System.currentTimeMillis();
		System.out.println(endTime1 - startTime1);
		
		//懶漢
		Long startTime = System.currentTimeMillis();
		for(int i = 0 ;i<100000000;i++)
		{
			Singleton instance = Singleton.getInstance();
		}
		Long endTime = System.currentTimeMillis();
		System.out.println(endTime - startTime);


經過屢次執行咱們能夠看一下結果如何:這裏咱們執行了三次

171     187    187 
5398    5398   5429

能夠明顯的看出餓漢比懶漢式單例性能上好,因此你使用了單例,若是在意性能的話,請使用餓漢式。

相關文章
相關標籤/搜索