什麼是單例模式 單例模式(Singleton Pattern)是一個比較簡單的模式,實際應用很廣泛,比如 Spring 中的Bean實例就是一個單例對象。 文章首發於作者微信公眾號【碼猿技術專欄】設計模式:單例模式,原創不易,喜歡的支持一下!!!! 定義:確保某一個類 只有一個實例,而且自行實例化並 ...
什麼是單例模式
- 單例模式(Singleton Pattern)是一個比較簡單的模式,實際應用很廣泛,比如 Spring 中的
Bean
實例就是一個單例對象。 - 文章首發於作者微信公眾號【碼猿技術專欄】設計模式:單例模式,原創不易,喜歡的支持一下!!!!
- 定義:確保某一個類 只有一個實例,而且自行實例化並向整個系統提供這個實例。
單例模式的優缺點
- 評價任何一種事務都要從兩個方面去看,不能單一的評價。下麵來看看單例模式有什麼優缺點。
優點
- 只有一個實例,減少了記憶體的開銷,尤其是頻繁的創建和銷毀實例。
- 單例模式可以避免對資源的多重占用,例如一個寫文件動作,由於只有一個實例存在 記憶體中,避免對同一個資源文件的同時寫操作。
- 單例模式可以在系統設置全局的訪問點,優化和共用資源訪問,例如可以設計一個單 例類,負責所有數據表的映射處理。
缺點
- 單例模式一般沒有介面,很難擴展(根據環境而定)。
- 單例模式與單一職責原則有衝突。一個類應該只實現一個邏輯,而不關心是否是單例的。
單例模式的實現
- 單例模式有很多的實現方式,但是各種實現的方式都有其優缺點,下麵來看看各種的實現方式。
- 單例模式的實現滿足以下幾點:
- 構造方法私有。
- 有一個靜態方法獲取該類的實例。
- 該類保證只有一個實例。
懶漢式
- 懶漢式是當用到這個對象的時候才會創建。
- 優點:只有用到的時候才會創建這個對象,因此節省資源。
- 簡單的實現如下:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 上面的代碼算是基本滿足了單例模式,但是不能滿足線程安全,一旦在多線程的環境下仍然是不能保證該類是單例的。
- 如何保證線程安全,當然是加鎖了,我們可以加線程同步鎖
synchronized
,實現如下:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- 此種實現方式雖然滿足了線程安全,但是加鎖勢必會影響性能。
餓漢式
- 餓漢式和懶漢式恰巧相反,在類載入的時候就創建實例。
- 優點:還沒用到就創建,浪費資源。
- 缺點:在類載入的時候就創建,線程安全。
- 實現如下:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
雙重校驗鎖
- 屬於懶載入的一種實現方式,採用雙重校驗的機制,在多線程的情況仍然保持高性能。
- 實現如下:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
匿名內部類/靜態內部類
- 利用靜態變數、靜態代碼塊、靜態方法都是在類載入的時候只載入一次的原理。
- 實現如下:
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
總結
- 單例模式的實現雖然很簡單,但是也要確保實現的性能和線程安全的問題。
- 單例模式的實現主流的就是以上介紹的幾種,分別是
懶漢式線程不安全
、懶漢式線程安全
、餓漢式
、雙重校驗鎖的實現
、靜態內部類的實現
。這幾種方式各有優缺點,陳某推薦使用靜態內部類的實現方式。 - 單例模式也是Spring使用的一種設計模式,保證了
Bean
的單實例才能管理和監控Bean的創建和銷毀。