“單例”模式與它在原始碼中的運用

爬蜥發表於2019-05-04

單例是指一個類僅有一個例項,通過提供的方法來作為全域性的訪問點

“單例”模式與它在原始碼中的運用
實現例子如下

public enum SingleTonEnum{
    INSTANCE;
    public static final SingleTonEnum getInstance(){
        return INSTANCE;
    }
}
複製程式碼

單例的優勢

  • 對訪問物件的嚴格控制
  • 不存在頻繁建立物件與物件GC帶來的消耗

單例多種實現方式對比

單例實現的最困難方式在於,如何才能保證“全域性”有且僅有一個實現,這裡的“全域性”則是針對不同的使用場景來做各自的應用即可。比如現在的應用都會部署到多臺機器上,每臺機器上都會有各自的jvm,那是否有必要保證所有的機器上都是同一個單例呢?或者可以僅僅把全侷限定在單個jvm呢?

一般來講,限定在jvm即可

當前一般的實現方式包括 使用列舉雙重檢查靜態內部類與餓漢式等等

餓漢式與靜態內部類相比,區別在於建立例項的時機,靜態內部類需要用到的時候才載入,餓漢式則相當於類載入的時候就建立,餓漢實現的例子比如jdk自帶的 Runtime 類,就是典型的應用

  • 列舉:能夠自適應序列化、反射、無法克隆
  • 雙重檢查:序列化、克隆業務場景需要特殊處理,當然,如果場景不需要支援序列化和克隆則是沒有問題,在反射上則是無法避免只實現單例
  • 靜態內部類:序列化、克隆場景需要特殊處理,同樣不需要這些的場景也是沒有問題,另外和雙重檢查一樣,無法避免反射只有單例

歡迎找到反射實現單例的同學一起探討,個人驗證程式碼戳這裡

另外對於自定義類載入器,只要是遵循雙親載入模式的類載入器都能實現單例

實際上沒有用到自己的類載入器,實現相同的類載入器

各實現方式在不同場景下驗證單例方式詳情請戳這裡

spring中對bean設定 scope 為 singleton

spring可以在bean檔案中設定建立的bean指定使用域為"singleton"

<bean id="paxi" class="maokitty.paxi"></bean>
複製程式碼

這種方式它預設就是實現了一個singleton,它是針對每個IOC容器實現的

官網文件戳這裡

當然通過指定不同的id,它也會為成功的建立另一個例項,這也就是單例"全域性"所特定的範疇。spring singleton原始碼追蹤記錄請戳這裡

需要單例的一些場景

不希望其它地方再建立一個例項的場景

引用

單例模式的演進
如何創造出一個好的單例
spring的單例問題

相關文章