思想:
相比於懶漢以及餓漢模式,靜態內部類模式(一般也被稱為 Holder)是許多人推薦的一種單例的實現方式,因為相比懶漢模式,它用更少的代碼量達到了延遲加載的目的。
顧名思義,這種模式使用了一個私有的靜態內部類,來存儲外部類的單例,這種靜態內部類,一般稱為 Holder。
而利用靜態內部類的特性,外部類的 getinstance() 方法,可以直接指向 Holder 持有的對象。
public final class StaticInnerSingleton { private StaticInnerSingleton() { if (SingletonHolder.instance != null) { throw new IllegalStateException(); } } private static class SingletonHolder { private static StaticInnerSingleton instance = new StaticInnerSingleton(); } public static StaticInnerSingleton getInstance() { return SingletonHolder.instance; } }
- 反射能否打破單例?
首先,對外部類的私有構造器中加入 instance==null 的判斷,防止反射入侵外部類。
其次,靜態內部類保證了從外部很難獲取 SingletonHolder 的 Class 對象,從而保證了內部類不會被反射。
- 多線程能否打破單例?
Holder 模式借用了餓漢模式的優勢,就是在加載類(內部類)的同時對 instance 對象進行初始化。
由於自始至終類只會加載一次,所以即使在多線程的情況下,也能夠保持單例的性質。
- 優勢?劣勢?
優勢:兼顧了懶漢模式的內存優化(使用時才初始化)以及餓漢模式的安全性(不會被反射入侵)。
劣勢:需要多加載一個類;相比於懶漢模式,Holder 創建的單例,只能通過 JVM 去控制器生命周期,不能手動 destroy。