定義
單例模式(Singleton Pattern)是一個比較簡單的模式,其定義如下:Ensure a class has only one instance, and provide a globalpoint of access to it.(確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。)
通用代碼
public class Singleton {
private static final Singleton instance = new Singleton();
// 限制產(chǎn)生多個對象
private Singleton() {}
// 通過該方法獲得實例對象
public static Singleton getInstance() {
return instance;
}
public static void doSomething() {
}
}
優(yōu)點
- 在內(nèi)存中只有一個實例,不必頻繁創(chuàng)建銷毀,節(jié)約時空。
- 避免對資源的多重占用
- 可以在系統(tǒng)設(shè)置全局的訪問點
缺點
- 一般沒有接口,擴展很困難
- 在并行開發(fā)環(huán)境中,如果單例模式?jīng)]有完成,是不能進行測試的
- 單例模式與單一職責(zé)原則有沖突
使用場景
在一個系統(tǒng)中,要求一個類有且僅有一個對象,如果出現(xiàn)多個對象就會出現(xiàn)“不良反應(yīng)”,可以采用單例模式。
餓漢式和懶漢式
上述通用代碼為“餓漢式單例”,在一開始便初始化instance。還有一種“懶漢式單例”,在首次調(diào)用getInstance時初始化對象,但在高并發(fā)的情況下會出現(xiàn)線程同步問題,產(chǎn)生兩個instance,方法是加入關(guān)鍵字synchronized。
實現(xiàn)代碼如下:
public class Singleton {
private static Singleton instance = null;
// 限制產(chǎn)生多個對象
private Singleton() {}
// 通過該方法獲得實例對象
public static synchronized Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
public static void doSomething() {
}
}
注意事項
如果我們的一個單例對象在內(nèi)存中長久不使用,JVM就認為這個對象是一個垃圾,在CPU資源空閑的情況下該對象會被清理掉,下次再調(diào)用時就需要重新產(chǎn)生一個對象。如果我們在應(yīng)用中使用單例類作為有狀態(tài)值(如計數(shù)器)的管理,則會出現(xiàn)恢復(fù)原狀的情況,應(yīng)用就會出現(xiàn)故障。如果確實需要采用單例模式來記錄有狀態(tài)的值,可以使用Spring框架中的bean讓對象長久駐留內(nèi)存。
其他探究
餓漢式在類裝載時就會加載對象,而懶漢式每次進入getInstance方法都需要同步,浪費了許多判斷時間。有沒有一種實現(xiàn)方法能夠同時改進這兩個缺點呢?
我們可以利用JVM里的內(nèi)部類來實現(xiàn),保證線程安全性。代碼如下:
public class Singleton {
// 靜態(tài)的成員式內(nèi)部類,只有被調(diào)用到時才會加載
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
// 私有化構(gòu)造方法
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public static void doSomething() {
}
}