我的Java設計模式-單例模式

Jet啟思發表於2017-10-26

  就算不懂設計模式的兄弟姐妹們,想必也聽說過單例模式,並且在專案中也會用上。但是,真正理解和熟悉單例模式的人有幾個呢?接下來我們一起來學習設計模式中最簡單的模式之一——單例模式

一、為什麼叫單例模式?

  “baby,你就是我的唯一,兩個世界都變形,回去談何容易...”。咳咳~就先唱到這吧,入正題。每次提起單例模式,筆者都會哼起這首王力巨集的《唯一》。為什麼?這首歌哪裡吸引我了?就是“唯一”這兩個非常有糞量的字。

斯大林時期的蘇聯,個人崇拜達到相當嚴重的程度。然而為什麼會導致個人崇拜呢?很簡單,那就是“只有一個斯大林,只有一個領導人”!不允許出現兩個或者多個領導人,國家政務、外交等等大事小事都需要斯大林來發號施令。

定義

  保證一個類只有一個例項,並且整個系統能訪問該例項。

特點

  1. 單例類保證只有一個例項
  2. 單例類必須自己建立自己的唯一例項
  3. 單例類提供給系統提供該唯一例項

單例的定義也就是這麼簡單,還不明白?直白點就是該類只能new一個物件,不允許new第二個物件,而系統訪問的就是該物件。
那有什麼辦法保證只有一個領導人斯大林呢?較常見的兩種方式:餓漢式懶漢式

二、實戰

UML圖

這裡提示一點,在學習設計模式的時候,UML圖會讓你更容易,而且深刻的去理解到該模式的核心。況且,UML圖也是成為專案管理者必備的技能。

單例模式UML圖.png
單例模式UML圖.png

上程式碼

如何確保一個系統只產生一個例項?這裡必須使用private修飾建構函式,並且在建構函式裡邊例項化。

前面提到了單例模式比較常見的兩種方式:餓漢式懶漢式。下面我們來具體看看到底有多餓,以及到底有多懶!

1、餓漢式

首先,來看一下餓漢式單例模式。

餓漢式單例程式碼如下:

public class EagerSingleton {

    private static EagerSingleton singleton = new EagerSingleton();

    private EagerSingleton() {
    } 

    public static EagerSingleton getSingleton() {
        return singleton;
    }
}複製程式碼

  注意,這裡獲取例項必須使用靜態方法,要不然類外部無法訪問通過該方法得到唯一例項。

“餓漢式”顧名思義,已經等不及外部需要用到的時候才例項化,於是在裝載類的時候就建立物件例項,一個自力更生的好榜樣~

餓漢式單例存在的問題主要是:既然在初始化的時候就已經裝載類,必然會消耗記憶體。

2、懶漢式

懶漢式單例程式碼如下:

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關鍵字對效能有所影響,因此不推薦使用,這裡也不做介紹了。當然,選擇哪一種方式是根據個人實際專案的情況來選用的。

先彆著急走,接下來登場的是比較完美的實現單例模式的方式列舉單例

3、列舉單例

老規矩,先上程式碼:

public enum Singleton {

    singleton;

    public void singletonFunc() { // 該單例需要實現的功能
    }

}複製程式碼

  是不是很簡單?而且因為自動序列化機制,保證了執行緒的絕對安全。三個詞概括該方式:簡單、高效、安全

三、總結

  好了,設計模式系列的第一篇到這就結束了。大家覺得哪裡需要改進,或者是需要筆者提供支援的可以下邊留言。剛開始的模式大家都比較容易理解,接下來才是重頭戲。下一篇的設計模式是:工廠方法模式

設計模式Java原始碼GitHub下載:https://github.com/jetLee92/DesignPattern

AndroidJet的開發之路.jpg
AndroidJet的開發之路.jpg

相關文章