1. 程式人生 > >面試題2:實現Singleton模式

面試題2:實現Singleton模式

題目:設計一個類,我們只能生成該類的一個例項

思路:

1)不能開發類的構造方法,不然誰都可以通過構造方法搭建,所以將構造方法私有化;

2)建立一個靜態例項,根據需要建立一個例項,但也要將該例項私有化,防止外部獲取該例項時例項還未建立;

3)建立一個方法獲取2中的靜態例項。

解法一:(只適合單執行緒)

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

缺點:只適合單執行緒環境,多執行緒下,如果兩個執行緒同時判斷instance是否為空,且instance確實沒有建立,那兩個執行緒就會同時建立一個例項,就不符合題目要求了

解法二:(適合多執行緒,但效率低)

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

缺點:每次獲取例項時都要等待獲取物件鎖和加同步鎖,效率慢

解法三:(適合多執行緒,效率也高)

public class Singleton {
	private Singleton(){
	}
	private static Singleton instance=null;
	public static Singleton Instance(){

		if(instance==null){
			synchronized (Singleton.class) {
				if(instance==null){
					instance=new Singleton();
				}
			}
		}
		return instance;
	}
}

分析:用兩個if判斷來提高效率,這樣當instance被建立之後,就不用被加鎖解鎖了,不過程式碼複雜,容易出錯。

解法四:(強烈推薦)

public class Singleton {
	private Singleton(){
	}
	private static Singleton instance=new Singleton();
	public static Singleton Instance(){
		return instance;
	}
	
}

分析:直接在初始化靜態變數時就建立例項,這樣只要類被呼叫的時候就會建立一個例項,如果在類中建立一個靜態方法,呼叫該靜態方法,即使此時不會使用該例項,也會建立該例項,因為靜態變數和靜態程式碼塊只要類被呼叫就會被初始化;當然,如果Singleton.class.getName()不會初始化靜態變數和靜態程式碼塊,因為JVM在載入類的過程中分為五個階段:載入、驗證、準備、解析、初始化,靜態變數和靜態程式碼塊的初始化發生在初始化階段,類.class發生在載入階段。

解法五:(強烈推薦)

public class Singleton {
	private Singleton(){
	}
	public static Singleton Instance(){
		return InstanceFactory.instance;
	}
	static class InstanceFactory{
		 private static final Singleton instance=new Singleton();
	};
	
}

分析:在需要的時候再建立例項,因為靜態內部類只有在本身被外部類呼叫時才會初始化,就算建立一個外部類的例項,執行外部類的方法,只要沒有執行到內部類的程式碼,靜態內部類就不會被初始化。

今天努力一點點,以後輕鬆一點點。