Singleton 是一種創(chuàng)建性模型,它用來確保只產(chǎn)生一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn).對(duì)一些類來說,保證只有一個(gè)實(shí)例是很重要的,比如有的時(shí)候,數(shù)據(jù)庫連接或 Socket 連接要受到一定的限制,必須保持同一時(shí)間只能有一個(gè)連接的存在.再舉個(gè)例子,集合中的 set 中不能包含重復(fù)的元素,添加到set里的對(duì)象必須是唯一的,如果重復(fù)的值添加到 set,它只接受一個(gè)實(shí)例.JDK中正式運(yùn)用了Singleton模式來實(shí)現(xiàn) set 的這一特性,大家可以查看java.util.Collections里的內(nèi)部靜態(tài)類SingletonSet的原代碼.其實(shí)Singleton是最簡(jiǎn)單但也是應(yīng)用最廣泛的模式之一,在 JDK 中隨處可見.
簡(jiǎn)單分析
為了實(shí)現(xiàn) Singleton 模式,我們需要的是一個(gè)靜態(tài)的變量,能夠在不創(chuàng)建對(duì)象的情況下記憶是否已經(jīng)產(chǎn)生過實(shí)例了.靜態(tài)變量或靜態(tài)方法都可以在不產(chǎn)生具體實(shí)例的情況下直接調(diào)用,這樣的變量或方法不會(huì)因?yàn)轭惖膶?shí)例化而有所改變.在圖1的結(jié)構(gòu)中可以看到,uniqueInstance 就是這個(gè)獨(dú)立的靜態(tài)變量,它可以記憶對(duì)象是否已經(jīng)實(shí)例化了,在靜態(tài)方法 Instance 中對(duì)這個(gè)變量進(jìn)行判斷,若沒有實(shí)例化過就產(chǎn)生一個(gè)新的對(duì)象,如果已經(jīng)實(shí)例化了則不再產(chǎn)生新的對(duì)象,仍然返回以前產(chǎn)生的實(shí)例.
圖1: Singleton 模式結(jié)構(gòu)
具體實(shí)施
實(shí)現(xiàn) Singleton 模式的辦法通常有三種.
一. 用靜態(tài)方法實(shí)現(xiàn) Singleton 這種方法是使用靜態(tài)方法來監(jiān)視實(shí)例的創(chuàng)建.為了防止創(chuàng)建一個(gè)以上的實(shí)例,我們最好把構(gòu)造器聲明為 private.
這樣可以防止客戶程序員通過除由我們提供的方法之外的任意方式來創(chuàng)建一個(gè)實(shí)例,如果不把構(gòu)造器聲明為private,編譯器就會(huì)自作聰明的自動(dòng)同步一個(gè)默認(rèn)的friendly構(gòu)造器.這種實(shí)現(xiàn)方法是最常見的,也就是圖1中結(jié)構(gòu)的標(biāo)準(zhǔn)實(shí)現(xiàn).
singletonTest運(yùn)行結(jié)果是:
Creating one instance
Creating two instance
Only one instance allowed
可以看出,第一個(gè)實(shí)例順利創(chuàng)建,第二個(gè)實(shí)例創(chuàng)建實(shí)拋出了我們自定義的異常.
三. 用注冊(cè)器機(jī)制來創(chuàng)建 Singleton 首先用集合中的Hashtable 和Enumeration來實(shí)現(xiàn)addItem(Object key, Object value),getItem(Object key), ,removeItem(Object key)等方法實(shí)現(xiàn)一個(gè)管理器,將key和value一一關(guān)聯(lián)起來,客戶程序員創(chuàng)建實(shí)例前首先用addItem方法進(jìn)行注冊(cè),再用getItem方法獲取實(shí)例.Hashtable中的key是唯一的,從而保證創(chuàng)建的實(shí)例是唯一的,具體實(shí)現(xiàn)限于篇幅不再細(xì)說,在Prototype模型的應(yīng)用一文中我將會(huì)給出一個(gè)實(shí)現(xiàn)注冊(cè)器的代碼.用注冊(cè)器機(jī)制來創(chuàng)建 Singleton模式的好處是易于管理,可以同時(shí)控制多個(gè)不同類型的Singleton 實(shí)例.
小結(jié)
Singleton模式可以方便的進(jìn)行擴(kuò)充,產(chǎn)生指定數(shù)目的實(shí)例.
在The Design Patterns Java Companion 一書中曾提到過用靜態(tài)類的方式來實(shí)現(xiàn) Singleton模式,并指出java.lang.Math就是一個(gè)例子,這里我并不表示贊同,因?yàn)镸ath并不是一個(gè)真正的對(duì)象,我們只是直接調(diào)用Math類所包裝的靜態(tài)方法而已,根本就沒有創(chuàng)建實(shí)例的過程,又從何說起只產(chǎn)生一個(gè)實(shí)例呢?這個(gè)問題我曾到Javaranch的論壇上發(fā)過帖子,所有回帖的人也都是對(duì)這一觀點(diǎn)持否定態(tài)度. 在多線程的程序中,singleton可能會(huì)變的不可靠,可能會(huì)出現(xiàn)多個(gè)實(shí)例,解決的辦法很簡(jiǎn)單,加個(gè)同步修飾符: public static synchronized Singleton getInstance(). 這樣就保證了線程的安全性. 最后要說的是大家可能會(huì)看見一些其他實(shí)現(xiàn)Singleton模式的方法,因?yàn)槟J皆诰唧w的應(yīng)用時(shí)是靈活的,不是一成不變的,并沒有一個(gè)固定的做法,但大都是上面幾種方法的變形.
0
喜歡他,就推薦他上首頁吧^_^
0371-86068866
4008887269
cndesign@163.com
CND設(shè)計(jì)網(wǎng)(CNDESIGN)會(huì)員所發(fā)布展示的 “原創(chuàng)作品/文章” 版權(quán)歸原作者所有,任何商業(yè)用途均需聯(lián)系作者。如未經(jīng)授權(quán)用作他處,作者將保留追究侵權(quán)者法律責(zé)任的權(quán)利。
Copyright ©2006-2019 CND設(shè)計(jì)網(wǎng)
移動(dòng) Android 版 豫 ICP 備16038122號(hào)-2 豫公網(wǎng)安備 41019702002261號(hào)