單例模式與靜態(tài)類(一個(gè)類,所有方法為靜態(tài)方法)是另一個(gè)非常有趣的問(wèn)題,由于單例模式和靜態(tài)類都具有良好的訪問(wèn)性,它們之間有許多相似之處,例如,兩者可以直接使用而無(wú)須創(chuàng)建對(duì)象,都可提交唯一實(shí)例,在一個(gè)非常高的高度上看起來(lái)它們都為是用于同樣的任務(wù)。那么Java中單例模式與靜態(tài)的區(qū)別有哪些呢?
接下來(lái),我們會(huì)了解什么Java中的什么地方使用單例模式,什么時(shí)候使用靜態(tài)類更好,順便說(shuō)下,JDK中有幾個(gè)關(guān)于兩者的例子,并且這例子非常聰明的,例如java.lang.Math是一個(gè)final類,并且其方法為靜態(tài)方法,另一方面java.lang.Runtime是一個(gè)單例的類。對(duì)于那些不熟悉單例模式或靜態(tài)類的人,靜態(tài)類就是一個(gè)Java類,它僅包含靜態(tài)方法,一個(gè)非常好靜態(tài)類的例子就是java.lang.Math,它包括了許多為不同數(shù)據(jù)功能實(shí)現(xiàn)工具方法,例如sqrt(),而單例類,在整個(gè)應(yīng)用生命周期內(nèi)只有一個(gè)實(shí)例,例如java.lang.Runtime。
什么時(shí)候在Java中使用靜態(tài)類替換單例
確實(shí)存在一些場(chǎng)景,靜態(tài)類比單例更適合,這個(gè)場(chǎng)景中主要的一個(gè)例子就是java.lang.Math,它不是單例的,其所有方法都是靜態(tài)方法,這里我給出幾個(gè)場(chǎng)景,我覺得使用靜態(tài)類比單例模式更適合。
1)如果你的單例不需要維護(hù)任何狀態(tài),僅僅提供全局訪問(wèn)的方法,這種情況考慮使用靜態(tài)類,靜態(tài)方法比單例更快,因?yàn)殪o態(tài)的綁定是在編譯期就進(jìn)行的。但是要記住,不建議在靜態(tài)類中維護(hù)狀態(tài)信息,特別是在并發(fā)環(huán)境中,若無(wú)適當(dāng)?shù)耐酱胧┒薷亩嗑€程并發(fā)時(shí),會(huì)導(dǎo)致壞的競(jìng)態(tài)條件。
如果你需要將一些工具方法集中在一起時(shí),你可以選擇使用靜態(tài)方法,但是別的東西,要求單例訪問(wèn)資源時(shí),應(yīng)該使用單例模式。
Java中單例與靜態(tài)的區(qū)別
它們基本的區(qū)別一個(gè)表現(xiàn)類,一個(gè)表現(xiàn)方法,下面列幾條它們之間的區(qū)別。
1)靜態(tài)類比單例具有更好的性能,因?yàn)殪o態(tài)方法在編譯期綁定。
2)再次,它們的區(qū)別是override的能力,因Java中的靜態(tài)方法是不可以覆蓋的,這就導(dǎo)致其木有太多的靈活性,另一面,你可通過(guò)繼承的方式覆蓋單例類中定義的方法。
3)靜態(tài)類很難模擬,因此難于單例測(cè)試,單例更容易模擬,因?yàn)橐脖褥o態(tài)類易于編寫單元測(cè)試,不論什么單例期望什么,你都可以傳遞模擬對(duì)象,例如構(gòu)造方法或方法參數(shù)。
4)如果你的需求中需要維護(hù)狀態(tài)信息,則單例比靜態(tài)類更適合,因?yàn)楹笳咴诰S護(hù)狀態(tài)信息方面是非??膳碌?,并導(dǎo)致狡滑的bug。
5)如果是一個(gè)非常重的對(duì)象,單例可以懶加載,但是靜態(tài)類沒有這樣的優(yōu)勢(shì),并且非常熱切的加載。
6)許多依賴注入的框架對(duì)單例都有良好的管理,例如Spring,使用它們非常容易。
兩者之間的這些區(qū)別,有助于我們?cè)诿鎸?duì)一些場(chǎng)景時(shí)做出選擇,下一節(jié)中了解什么時(shí)候選擇單例而不是靜態(tài)類。
Java中,選擇單例而不是靜態(tài)類的優(yōu)點(diǎn)
單例與靜態(tài)主要的優(yōu)點(diǎn)是前者比后者更具有面向?qū)ο蟮哪芰Γ褂脝卫?,可以通過(guò)繼承和多態(tài)擴(kuò)展基類,實(shí)現(xiàn)接口和更有能力提供不同的實(shí)現(xiàn),如果我們討論java.lang.Runtime,在Java中它是單例,調(diào)用getRuntime()方法,會(huì)基于不同的JVM返回不同的實(shí)現(xiàn),但也保證了每個(gè)JVM中實(shí)有一個(gè)實(shí)例,如果java.lang.Runtime是一個(gè)靜態(tài)類,不太可能因不同的JVM返回不同的實(shí)現(xiàn)。
這就是Java中單例與靜態(tài)類的區(qū)別,當(dāng)你需要一個(gè)全OO能力的對(duì)象時(shí),選擇單例,如果僅僅是將一些靜態(tài)方法預(yù)售,使用靜態(tài)類。
1【行業(yè)秘笈】2024 年平面設(shè)計(jì)趨勢(shì)有哪些?
2【職場(chǎng)秘笈】前端和后端究竟有什么區(qū)別?到底應(yīng)該怎么選呢?
3【職場(chǎng)秘笈】面對(duì)職業(yè)“低谷”期,除了焦慮、抱怨,我們還能做些什么?
4【職場(chǎng)秘籍】沒靈感,設(shè)計(jì)總監(jiān)是怎么設(shè)計(jì)Logo的?
5華信智原春季師資培訓(xùn)圓滿落幕|技術(shù)賦能教學(xué),助推品質(zhì)課堂
6【職場(chǎng)秘笈】學(xué)會(huì)這幾招,再也不用為簡(jiǎn)歷的項(xiàng)目經(jīng)歷發(fā)愁!
1【人才共建】華信智原與世紀(jì)恒通科技股份有限公司達(dá)成人才共建戰(zhàn)略
2【開班典禮】從這一刻出發(fā),為夢(mèng)想助力前行!
3【總監(jiān)進(jìn)課堂】大咖教你試用期如何簽合同?
4華信智原與阿里云南區(qū)運(yùn)營(yíng)商簽署合作