1. 程式人生 > >Java單例模式——靜態內部類實現

Java單例模式——靜態內部類實現

Singleton是眾多設計模式中最容易理解的一種,也是眾多設計模式中較為重要的一種設計模式。

Singleton模式實現的重點在於將建構函式私有化(private),並通過提供靜態公有函式(public synchronized static xxx getInstance)來獲取定義在類中的靜態私有成員(private static xxx instance),通過一個簡單的判斷靜態例項是否為空來控制這個類只能夠new一次,即控制了一個類只能有單個例項,一般的實現如下程式碼所示:

package com.study.dp.singleton;

/**
 * 傳統方式實現單例模式
 * @author CrazyPig
 *
 */
public class TraditionalSingletion {
	
	// 單例項
	private static TraditionalSingletion instance;
	
	// 不讓new
	private TraditionalSingletion() {
		System.out.println("private TraditionalSingletion()");
	}
	
	public synchronized static TraditionalSingletion getInstance() {
		System.out.println("TraditionalSingletion getInstance()");
		if(instance == null) {
			System.out.println("instance = new TraditionalSingletion()");
			instance = new TraditionalSingletion();
		}
		return instance;
	}
	
	public static void main(String[] args) {
		TraditionalSingletion instance = TraditionalSingletion.getInstance();
		System.out.println("========================================");
		TraditionalSingletion instance01 = TraditionalSingletion.getInstance();
		System.out.println("========================================");
		TraditionalSingletion instance02 = TraditionalSingletion.getInstance();
	}

}

今天偶然在一篇文章中看到另外一種巧妙的做法,通過將這個單例項的引用變數定義在靜態內部類中,來實現單例,這樣可以做到不用if條件進行判斷,並且是多執行緒安全的(由jvm保證)。這個特殊的做法如下所示:
package com.study.dp.singleton;

/**
 * 靜態內部類實現單例模式
 * @author CrazyPig
 *
 */
public class SpecialSingleton {
	
	// 靜態內部類
	private static class NestClass {
		private static SpecialSingleton instance;
		static {
			System.out.println("instance = new SingletonTest()");
			instance = new SpecialSingleton();
		}
	}
	
	// 不能直接new
	private SpecialSingleton() {
		System.out.println("private SingletonTest()");
	}
	
	public static SpecialSingleton getInstance() {
		System.out.println("SingletonTest getInstance()");
		return NestClass.instance;
	}
	
	public static void main(String[] args) {
		SpecialSingleton instance = SpecialSingleton.getInstance();
		System.out.println("========================================");
		SpecialSingleton instance01 = SpecialSingleton.getInstance();
		System.out.println("========================================");
		SpecialSingleton instance02 = SpecialSingleton.getInstance();
	}

}
當第一次引用getInstance()方法的時候,訪問靜態內部類中的靜態成員變數,此時該內部類需要呼叫static程式碼塊(因為首次訪問該類)。而後再次訪問getInstance()方法會直接返回instace引用。這種做法相對於傳統做法更加巧妙。