單元素的列舉型別已經成為實現Singleton的最佳方法
阿新 • • 發佈:2019-02-03
一、概述
Singleton模式是在程式設計實踐中應用最廣泛的幾種設計模式之一。以前常用的是下面的這種方法:
public class Singleton
{
private volatile static Singleton instance;
private Singleton(){};
public static Singleton getInstance()
{
if (instance == null)
{
synchronized (Singleton.class)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
這種方法稱為雙重校驗鎖,極不推薦使用。
二、其他實現Singleton的方法
1、餓漢式:
public class Singleton
{
public static final Singleton INSTANCE = new Singleton();
private Singleton(){};
}
2、餓漢式變種(1)
public class Singleton
{
private static final Singleton INSTANCE = new Singleton();
private Singleton(){};
public static Singleton getInstance()
{
return INSTANCE;
}
}
這兩種方式都要求使用私有構造器,私有構造器僅被呼叫一次,用來例項化靜態final域Singleton.INSTANCE。
3、餓漢式變種(2) 類初始化的時候例項化instance
public class Singleton
{
private static Singleton instance = null;
private Singleton(){};
static
{
instance = new Singleton();
}
public static Singleton getInstance()
{
return instance;
}
}
4、靜態內部類
public class Singleton
{
private static class SingletonHolder
{
private static final Singleton instance = new Singleton();
}
private Singleton(){};
public static Singleton getInstance()
{
return SingletonHolder.instance;
}
}
這四種方法都可以藉助AccessibleObject.setAccessible方法,通過反射機制,呼叫私有構造器建立新的例項,如下圖:
可見s1 == s2為fasle,說明建立了兩個例項,也用失去了Singleton屬性。如果需要抵禦這種攻擊,可以修改構造器,讓它在被要求建立第二個例項的時候丟擲異常。
三、使用單元素的列舉實現Singleton
public enum Singleton
{
INSTANCE;
public void dosomething()
{
System.out.println(this + " is speaking!");
}
}
先看下執行後的結果:
使用單元素的列舉型別實現Singleton時,通過反射機制去建立新的例項時會丟擲異常。
和以前的s1 == s2對比,可以看到使用單元素的列舉型別在功能上與公有域方法相近,但是它更加簡潔,並且無償得提供了序列化機制,絕對防止多次例項化。