單例模式與靜態類(一個類,所有方法為靜態方法)是另一個非常有趣的問題,在《Java中有關單例模式的面試問題》博文中露掉了,由於單例模式和靜態類都具有良好的訪問性,它們之間有許多相似之處,例如,兩者可以直接使用而無須創建對象,都可提交唯一實例,在一個非常高的高度上看起來它們都為是用於同樣的任務。由於它們具有較多的相似性,面試官常常會問一些類似為神馬使用單例模式替換靜態方法?你能使用靜態類替換單例模式嗎?Java中單例模式與靜態的區別有那些?等這樣的問題,為回答這些問題,記住他們單例模式和靜態方法之間基本的區別是非常重要的,前者給你一個Object,后者僅僅提供靜態方法,由於對像比方法具有較強的能力,可以指導你神馬時候使用單例模式與靜態方法。
在本文中,我們會了解神馬Java中的神馬地方使用單例模式,神馬時候使用靜態類更好,順便說下,JDK中有幾個關於兩者的例子,並且這例子非常聰明的,例如java.lang.Math是一個final類,並且其方法為靜態方法,另一方面java.lang.Runtime是一個單例的類。對於那些不熟悉單例模式或靜態類的人,靜態類就是一個Java類,它僅包含靜態方法,一個非常好靜態類的例子就是java.lang.Math,它包括了許多為不同數據功能實現工具方法,例如sqrt(),而單例類,在整個應用生命周期內只有一個實例,例如java.lang.Runtime。
神馬時候在Java中使用靜態類替換單例
確實存在一些場景,靜態類比單例更適合,這個場景中主要的一個例子就是java.lang.Math,它不是單例的,其所有方法都是靜態方法,這里我給出幾個場景,我覺得使用靜態類比單例模式更適合。
1) 如果你的單例不需要維護任何狀態,僅僅提供全局訪問的方法,這種情況考慮使用靜態類,靜態方法比單例更快,因為靜態的綁定是在編譯期就進行的。但是要記住,不建議在靜態類中維護狀態信息,特別是在並發環境中,若無適當的同步措施而修改多線程並發時,會導致壞的競態條件。
如果你需要將一些工具方法集中在一起時,你可以選擇使用靜態方法,但是別的東西,要求單例訪問資源時,應該使用單例模式。
Java中單例與靜態的區別
這是回答關於單例與靜態的第二面試問題,如我早些提到過的,它們基本的區別一個表現類,一個表現方法,下面列幾條它們之間的區別。
1) 靜態類比單例具有更好的性能,因為靜態方法在編譯期綁定。
2) 再次,它們的區別是override的能力,因Java中的靜態方法是不可以覆蓋的,這就導致其木有太多的靈活性,另一面,你可通過繼承的方式覆蓋單例類中定義的方法。
3) 靜態類很難模擬,因此難於單例測試,單例更容易模擬,因為也比靜態類易於編寫單元測試,不論神馬單例期望神馬,你都可以傳遞模擬對象,例如構造方法或方法參數。
4) 如果你的需求中需要維護狀態信息,則單例比靜態類更適合,因為后者在維護狀態信息方面是非常可怕的,並導致狡滑的bug。
5) 如果是一個非常重的對象,單例可以懶加載,但是靜態類沒有這樣的優勢,並且非常熱切的加載。
6) 許多依賴注入的框架對單例都有良好的管理,例如Spring,使用它們非常容易。
兩者之間的這些區別,有助於我們在面對一些場景時做出選擇,下一節中了解神馬時候選擇單例而不是靜態類。
Java中,選擇單例而不是靜態類的優點
單例與靜態主要的優點是前者比后者更具有面向對象的能力,使用單例,可以通過繼承和多態擴展基類,實現接口和更有能力提供不同的實現,如果我們討論java.lang.Runtime,在Java中它是單例,調用getRuntime()方法,會基於不同的JVM返回不同的實現,但也保證了每個JVM中實有一個實例,如果java.lang.Runtime是一個靜態類,不太可能因不同的JVM返回不同的實現。
這就是Java中單例與靜態類的區別,當你需要一個全OO能力的對象時,選擇單例,如果僅僅是將一些靜態方法預售,使用靜態類。