1. 程式人生 > >【Java設計模式】單例模式

【Java設計模式】單例模式

package com.bufoon.test.gof.singleton;

/**
 * 顧名思義,比較懈怠,就是需要的時候才會去建立例項,
 * 這是經典的延遲載入思想,還有快取的實現思路;
 * 它會有執行緒安全問題,可以加鎖,但是會影響效率,
 * 典型的時間換空間的策略;
* @ClassName: LazySingleton  
* @Description: 懶漢式單例  
* @author anling.song  
* @date 2017年7月6日 下午4:20:09
 */
public class LazySingleton {

	private static LazySingleton instance = null;
	
	//私有化構造方法
	private LazySingleton(){}
	/**
	 * 執行緒安全問題
	 * @return
	 */
	public static LazySingleton getInstance1(){
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
	
	/**
	 * 加鎖能避免執行緒安全問題,但是效率有問題
	 * 因為每次呼叫都得先獲取鎖
	 * @return
	 */
	public synchronized static LazySingleton getInstance2(){
		if (instance == null) {
			instance = new LazySingleton();
		}
		return instance;
	}
	
	/**
	 * 加鎖的另外一種實現方式,只會在第一次生成例項的時候去獲取鎖
	 * 提高效率,雙重判斷加鎖,如果通過反射還是會破壞單例模式
	 * @return
	 */
	public static LazySingleton getInstance3(){
		if (instance == null) {
			synchronized (LazySingleton.class) {
				if (instance == null) {
					instance = new LazySingleton();
				}
			}
		}
		return instance;
	}
}
package com.bufoon.test.gof.singleton;

/**
 * 餓漢式就是比較著急,所以會在類載入的時候就建立例項,
 * 由於它是在類載入的時候就建立了,所以沒有執行緒安全的問題,
 * 但是浪費資源,空間換時間;
* @ClassName: HungrySingleton  
* @Description: 餓漢式單例 
* @author anling.song  
* @date 2017年7月6日 下午4:17:37
 */
public class HungrySingleton {

	private static HungrySingleton instance = new HungrySingleton();
	
	//私有化構造方法
	private HungrySingleton(){}
	
	public static HungrySingleton getInstance(){
		return instance;
	}
}
package com.bufoon.test.gof.singleton;

/**
 * 結合懶漢餓漢兩種實現都會有點小小的缺陷,
 * 能不能解決既能延遲載入,又不會有安全問題呢?
 * 因為static是由jvm去控制線同步的,所以能解決執行緒安全問題;
 * 在單例類內新增一個靜態內部類,靜態內部類初始化類例項;
* @ClassName: InnerStaticClassSingleton  
* @Description: 靜態內部類單例  
* @author anling.song  
* @date 2017年7月6日 下午4:29:14
 */
public class InnerStaticClassSingleton {

	private InnerStaticClassSingleton(){}
	
	/**
	 * 在真正呼叫的時候才會初始化,實現了延遲載入
	 * 執行緒安全由jvm底層控制,所以是執行緒安全的
	* @ClassName: InnerSingletonHolder  
	* @Description: 靜態內部類  
	* @author anling.song  
	* @date 2017年7月6日 下午4:30:36
	 */
	private static class InnerSingletonHolder{
		private static InnerStaticClassSingleton instance = new InnerStaticClassSingleton();
	}
	
	public static InnerStaticClassSingleton getInstance(){
		return InnerSingletonHolder.instance;
	}
}
package com.bufoon.test.gof.singleton;

import java.util.HashMap;
import java.util.Map;

/**
 * 在高效Java第二版上提到的一種實現方式,
 * 因為列舉的一個屬性就是代表列舉類自己,
 * 所以用來實現單例模式非常簡便和通俗易懂;
* @ClassName: EnumSingleton  
* @Description: 列舉單例類  
* @author anling.song  
* @date 2017年7月6日 下午4:33:10
 */
public enum EnumSingleton {

	enumInstance;
	
	// 存花式剎停動作分數儲存
	private Map<String, Integer> map = null;
	
	/**
	 * Enum構造方法,JVM會保證呼叫時只初始化一次
	 */
	private EnumSingleton(){
		System.out.println("初始化資料............");
		if (map == null) {
			map = new HashMap<String, Integer>();
		}
		map.put("V_TOE_TOE", 10);
		map.put("EIGHT_CROSS", 9);
		map.put("EAGLE", 8);
		map.put("BACKSLIDE", 6);
		map.put("PARRAL", 4);
	}
	
	public int getScore(String action){
		if ("".equals(action) || null == action || map == null) {
			return -1;
		}
		return map.get(action);
	}
	
	public static void main(String[] args) {
		EnumSingleton e1 = EnumSingleton.enumInstance;
		EnumSingleton e2 = EnumSingleton.enumInstance;
		// 確認列舉是否只初始化了一次構造方法
		System.out.println((e1 == e2) + "|" + (e1 == enumInstance) + "|" + (e2 == enumInstance));
		System.out.println("V_TOE_TOE 動作的評分為:" + enumInstance.getScore("V_TOE_TOE") + "分");
	}
}

5. 思考