二十三種設計模式之一單例模式

方式一:首先不考慮併發的情況下:

public class Singleton{
		private static  Singleton singleton  = null;                                                                     
		public Singleton getInstance(){                                                                                     
			if(null == singleton){                                                                                  
				 singleton = new Singleton();	                                                                  
			}                                                                                                                                    
		return singleton ;                                                                                                
	}
}

方式二:加鎖(不考慮效率)

	public class Solution {
		private  static Solution singleton = null;
		public  synchronized  static Solution getInstance(){
			if(null == singleton){
				singleton = new  Solution();
				}			
			return singleton;
		}			
	}

方式三:(雙重檢查加鎖DCL(Double-Check-Locked))

public class Solution {
	/**
	 * @return: The same instance of this class every time
	*/
	private static Solution singleton = null;
	    
	    public static Solution getInstance() {
	       if(singleton == null){
	           synchronized (Solution.class){
	               if(singleton == null){
	                   try{
	                        singleton = (Solution)Class.forName("Solution").newInstance();
	                   }catch(Exception e){
	                       e.printStackTrace();
	                   }
	               }
	           }
	       }
	        return singleton;
	    }
	};
								

它的工作原理是:首先檢查是否在沒有同步的情況下需要初始化,如果singleton引用不爲空,則無需初始化,直接使用它即可。否則就進行同步並再次檢查singleton是否被初始化,從而保證了只有一個線程對singleton執行初始化。但是:在第一次檢查的時候,由於沒有采用同步,有可能得到一個“僅被部分構造的對象”,從而得到一個不正確(尚未初始化完成)的對象。產生這種糟糕結果的原因那就是java內存模型的指令衝排序現象——jvm爲了優化程序性能而對指令重新排序執行的現象。
優化方案則是

public class Singleton{
	private volatile static Singleton singleton;
	public  static Singleton getInstance(){
		if(null == singleton){
			synchronized(Singleton.class){
				if(null == singleton){
					singleton = new Singleton();
					}
			}
		}
	return singleton;
	}
}

不過該優化方案在java5.0及更高的版本中才能生效。DCL的這種方案已經被廣泛的廢棄掉了。更通用的做法是採用延遲化佔位類模式
方式四:即非延遲性加載方式,在類創建的同時就實例化一個singleton靜態對象,在第一次調用的時候,速度會比延遲化加載模式要快,因爲已經初始化完成。

public class Solution{
	private static Solution singleton = new Solution();;
	public static  Solution getInstance(){
		return singleton;
	}
}

方式五:本質上同方式四沒有多大區別

public class Solution{
	private static Solution singleton = null;
	static {
		singleton = new Solution();
	}
	public static Solution getInstance(){
		return singleton;
	}
}

方式六:靜態內部類(延遲化佔位類方式) JVM推遲Solution的初始化操作,當開始調用getInstance()的時候Solution纔會初始化,從而達到懶加載的目的。

public class  TestClass{
	public static Solution getInstance(){
		return Solution.singleton;
	}
	 static class Solution{
		private static Solution singleton=new Solution();
	}

}

方式七:枚舉類型實現單例模式
避免序列化和反序列化得到單例對象不相同,以及通過反射機制調用對象的私有構造方法來構造單例對象的弊端:

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}
發佈了30 篇原創文章 · 獲贊 27 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章