如何以正確的姿勢(shì)寫(xiě)單例

Forever A Singleton

本文定位于理解和總結(jié)《Effective Java》的所講內(nèi)容,而不是翻譯逐工,因此不當(dāng)之處爹袁,還請(qǐng)廣大網(wǎng)友指出。

關(guān)于單例

單例是指僅需要被實(shí)例化一次的類(lèi)砸抛,在編程實(shí)踐中往往用于實(shí)現(xiàn)那些僅需要一個(gè)對(duì)象的系統(tǒng)模塊。單例模式的實(shí)現(xiàn)有很多種树枫,具體可參見(jiàn)這篇博客直焙,單例模式對(duì)其具體實(shí)現(xiàn)的基本要求只有兩個(gè):線程安全有且僅有一個(gè)實(shí)例

本文并不討論單例模式本身的優(yōu)劣砂轻,盡管這類(lèi)討論一直都有并將持續(xù)下去奔誓,實(shí)際上,單例模式廣泛應(yīng)用于編程實(shí)踐舔清,本文的主題是如何優(yōu)雅地實(shí)現(xiàn)單例丝里。

線程安全

線程安全分為兩部分,創(chuàng)建和獲取實(shí)例時(shí)的線程安全以及調(diào)用單例其他方法時(shí)的線程安全体谒,后一部分的線程安全由客戶端程序員保證,在此不做討論臼婆,實(shí)際上抒痒,創(chuàng)建和獲取實(shí)例時(shí)的線程安全,目前大多數(shù)的實(shí)現(xiàn)是可以保證的颁褂,比如:

// Singleton with public final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    // other methods
    public void leaveTheBuilding() { ... }    
}

類(lèi)加載過(guò)程的線程安全性保證了上述實(shí)現(xiàn)中實(shí)例創(chuàng)建過(guò)程的線程安全故响,而獲取該實(shí)例過(guò)程的線程安全性是顯而易見(jiàn)的(由public關(guān)鍵字決定)。
實(shí)際上颁独,對(duì)于大多數(shù)的單例實(shí)現(xiàn)形式而言彩届,線程安全是容易保證的,而有且僅有一個(gè)實(shí)例這個(gè)要求卻難以保證誓酒,往往需要增加一些特殊處理樟蠕。比如上述實(shí)現(xiàn)中贮聂,仍然可以通過(guò)反射的方法來(lái)創(chuàng)建一個(gè)新的實(shí)例;或者上述類(lèi)在實(shí)現(xiàn)Serializable接口之后寨辩,在反序列化該類(lèi)時(shí)吓懈,可以獲取一個(gè)新的實(shí)例。

關(guān)于如何增加“特殊處理”來(lái)保證上述實(shí)現(xiàn)中有且只有一個(gè)實(shí)例靡狞,將會(huì)在后續(xù)的文章中給出耻警。

有且僅有一個(gè)實(shí)例

很多人認(rèn)為線程安全比有且僅有一個(gè)實(shí)例更難保證,其實(shí)不然甸怕。要保證單例模式有且僅有一個(gè)實(shí)例甘穿,除了將構(gòu)造器設(shè)置為private之外,還要求實(shí)現(xiàn)類(lèi)能夠抵抗反射攻擊以及反序列化攻擊(在反序列化過(guò)程中產(chǎn)生新的實(shí)例)梢杭。在Java 1.5之后增加的枚舉類(lèi)型天然的符合上述要求温兼,因此利用枚舉來(lái)實(shí)現(xiàn)單例模式是一個(gè)很好的方案,遺憾的是式曲,目前該方法并沒(méi)有被廣泛采用妨托。其實(shí)現(xiàn)非常簡(jiǎn)單,如下:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding(){ ... }
}
  • 枚舉構(gòu)造器的訪問(wèn)修飾符只能是private
    這一特性保證了無(wú)法直接使用new關(guān)鍵字創(chuàng)建枚舉對(duì)象吝羞,既除了枚舉中定義的對(duì)象之外兰伤,外部程序無(wú)法創(chuàng)建對(duì)象。
  • 不能通過(guò)反射調(diào)用構(gòu)造器創(chuàng)建新的枚舉實(shí)例
    通過(guò)反射調(diào)用枚舉構(gòu)造器時(shí)會(huì)拋出java.lang.IllegalArgumentException異常钧排。
  • 枚舉類(lèi)型的反序列化過(guò)程不會(huì)產(chǎn)生新的實(shí)例敦腔。
    這一點(diǎn)由枚舉類(lèi)型本身保證,客戶端程序員無(wú)需做任何特殊處理恨溜。

當(dāng)然符衔,使用枚舉來(lái)實(shí)現(xiàn)單例模式也是線程安全的,也是通過(guò)類(lèi)加載過(guò)程的線程安全性來(lái)保證的糟袁。

綜上判族,在所有單例模式的實(shí)現(xiàn)中,枚舉以最優(yōu)雅的方式實(shí)現(xiàn)了線程安全项戴,保證了有且僅有一個(gè)實(shí)例形帮,并且使用起來(lái)非常簡(jiǎn)單,因此下次需要一個(gè)單例模式時(shí)周叮,請(qǐng)考慮使用枚舉辩撑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市仿耽,隨后出現(xiàn)的幾起案子合冀,更是在濱河造成了極大的恐慌,老刑警劉巖项贺,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件君躺,死亡現(xiàn)場(chǎng)離奇詭異峭判,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)晰洒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)朝抖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谍珊,你說(shuō)我怎么就攤上這事治宣。” “怎么了砌滞?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵侮邀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我贝润,道長(zhǎng)绊茧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任打掘,我火速辦了婚禮华畏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尊蚁。我一直安慰自己亡笑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布横朋。 她就那樣靜靜地躺著仑乌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琴锭。 梳的紋絲不亂的頭發(fā)上晰甚,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音决帖,去河邊找鬼厕九。 笑死,一個(gè)胖子當(dāng)著我的面吹牛地回,可吹牛的內(nèi)容都是我干的止剖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼落君,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了亭引?” 一聲冷哼從身側(cè)響起绎速,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焙蚓,沒(méi)想到半個(gè)月后纹冤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體洒宝,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年萌京,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雁歌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡知残,死狀恐怖靠瞎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情求妹,我是刑警寧澤乏盐,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站制恍,受9級(jí)特大地震影響父能,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜净神,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一何吝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鹃唯,春花似錦爱榕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至八匠,卻和暖如春絮爷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梨树。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工坑夯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人抡四。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓柜蜈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親指巡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子淑履,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡(jiǎn)單、最易理解的設(shè)計(jì)模式藻雪,也因?yàn)樗暮?jiǎn)潔易懂秘噪,是項(xiàng)目中最...
    成熱了閱讀 4,228評(píng)論 4 34
  • 1 場(chǎng)景問(wèn)題# 1.1 讀取配置文件的內(nèi)容## 考慮這樣一個(gè)應(yīng)用,讀取配置文件的內(nèi)容勉耀。 很多應(yīng)用項(xiàng)目指煎,都有與應(yīng)用相...
    七寸知架構(gòu)閱讀 6,673評(píng)論 12 68
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理蹋偏,服務(wù)發(fā)現(xiàn),斷路器至壤,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • 1.單例模式概述 (1)引言 單例模式是應(yīng)用最廣的模式之一威始,也是23種設(shè)計(jì)模式中最基本的一個(gè)。本文旨在總結(jié)通過(guò)Ja...
    曹豐斌閱讀 2,888評(píng)論 6 47
  • 【面試匯總】Java面試題-1Java面試題-2 【集合】Java集合及concurrent并發(fā)包總結(jié)(轉(zhuǎn))Jav...
    小強(qiáng)子同學(xué)閱讀 317評(píng)論 1 1