1 單例模式的實現場景
創建一個對象需要消耗過多的資源,如要訪問IO和數據庫等資源,爲避免產生多個對象消耗過多資源,需要考慮使用單例模式。
2 實現單例模式的幾個關鍵點
1)構造函數私有化
2)通過一個靜態方法或枚舉返回單例類對象
3)確保單例類的對象有且只有一個,特別是在多線程環境下
4)確保單例類的對象在反序列化時不會重新構建對象
反序列化操作提供了一個很特別的鉤子函數,類中具有一個私有的、被實例化的方法readResolve(),這個方法可以讓開發人員控制對象的反序列化。爲防止這種情況,需加入如下方法:
private Object readResolve() throws ObjectStreamException
{
return sInstance;
}
也就是在readResolve()方法中將sInstance對象返回,而不是默認的重新生成一個新的對象。
3 單例模式實現的幾種方式
懶漢式和DCL方式不建議使用,這裏都不做介紹。
3.1 餓漢式
public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
}
public static Singleton getInstance()
{
return instance;
}
}
優點:簡單。
缺點:第一次加載Singleton類時instance就被實例化,不管是否被使用,不是按需進行實例化。
3.2 靜態內部類單例模式
public class Singleton
{
private Singleton()
{
}
public static Singleton getInstance()
{
return SingletonHolder.sInstance;
}
private static class SingletonHolder
{
private static final Singleton sInstance = new Singleton();
}
}
這是推薦使用的單例模式實現方式。
3.3 枚舉單例
public enum SingletonEnum
{
INSTANCE;
public void doSomething()
{
........
}
}
只用SingletonEnum.INSTANCE即可獲得所需實例,默認枚舉實例的創建是線程安全的,並且在任何情況下它都是一個單例。不像以上方式,在反序列化時可以通過鉤子函數readResolve()去創建新的實例。枚舉不存在這個問題,反序列化也不會生成新的實例。