就算不懂設計模式的兄弟姐妹們,想必也據說過單例模式,而且在項目中也會用上。可是,真正理解和熟悉單例模式的人有幾個呢?接下來咱們一塊兒來學習設計模式中最簡單的模式之一——單例模式git
「baby,你就是個人惟一,兩個世界都變形,回去談何容易...」。咳咳~就先唱到這吧,入正題。每次提起單例模式,筆者都會哼起這首王力宏的《惟一》。爲何?這首歌哪裏吸引我了?就是「惟一」這兩個很是有糞量的字。github
斯大林時期的蘇聯,我的崇拜達到至關嚴重的程度。然而爲何會致使我的崇拜呢?很簡單,那就是「只有一個斯大林,只有一個領導人」!不容許出現兩個或者多個領導人,國家政務、外交等等大事小事都須要斯大林來發號施令。設計模式
保證一個類只有一個實例,而且整個系統能訪問該實例。安全
單例的定義也就是這麼簡單,還不明白?直白點就是該類只能new一個對象,不容許new第二個對象,而系統訪問的就是該對象。
那有什麼辦法保證只有一個領導人斯大林呢?較常見的兩種方式:餓漢式和懶漢式bash
這裏提示一點,在學習設計模式的時候,UML圖會讓你更容易,並且深入的去理解到該模式的核心。何況,UML圖也是成爲項目管理者必備的技能。函數
如何確保一個系統只產生一個實例?這裏必須使用private修飾構造函數,而且在構造函數裏邊實例化。post
前面提到了單例模式比較常見的兩種方式:餓漢式和懶漢式。下面咱們來具體看看到底有多餓,以及到底有多懶!性能
首先,來看一下餓漢式單例模式。學習
餓漢式單例代碼以下:ui
public class EagerSingleton {
private static EagerSingleton singleton = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getSingleton() {
return singleton;
}
}複製代碼
注意,這裏獲取實例必須使用靜態方法,要否則類外部沒法訪問經過該方法獲得惟一實例。
「餓漢式」顧名思義,已經等不及外部須要用到的時候才實例化,因而在裝載類的時候就建立對象實例,一個自力更生的好榜樣~
餓漢式單例存在的問題主要是:既然在初始化的時候就已經裝載類,必然會消耗內存。
懶漢式單例代碼以下:
public class LazySingleton {
private static LazySingleton singleton = null;
private LazySingleton() {
}
public static synchronized LazySingleton getSingleton() {
if (instance == null) {
singleton = new LazySingleton();
}
return singleton;
}
}複製代碼
這裏使用了synchronized進行同步,以保證線程安全
「懶漢式」的定義也容易理解,由於懶,因此當須要使用到該實例的時候纔去建立對象實例,在此以前不對類進行實例化。
懶漢式單例主要問題:因爲它的實現是線程安全的,會下降對實例的訪問速度,而且每次都須要進行判斷。
來到這的時候,既然上面兩個方式的單例都存在着問題,那有沒有一種方式,既能保證性能受到的影響小,而且能夠保證線程安全的呢?網上不少現有的資源都說起到雙重檢查加鎖,在我第一次看到這東西的時候就以爲名字都很麻煩,實際上它的實現也比較麻煩,還有就是volatile關鍵字對性能有所影響,所以不推薦使用,這裏也不作介紹了。固然,選擇哪種方式是根據我的實際項目的狀況來選用的。
先彆着急走,接下來登場的是比較完美的實現單例模式的方式枚舉單例
老規矩,先上代碼:
public enum Singleton {
singleton;
public void singletonFunc() { // 該單例須要實現的功能
}
}複製代碼
是否是很簡單?並且由於自動序列化機制,保證了線程的絕對安全。三個詞歸納該方式:簡單、高效、安全
好了,設計模式系列的第一篇到這就結束了。你們以爲哪裏須要改進,或者是須要筆者提供支持的能夠下邊留言。剛開始的模式你們都比較容易理解,接下來纔是重頭戲。下一篇的設計模式是:工廠方法模式。
設計模式Java源碼GitHub下載:https://github.com/jetLee92/DesignPattern