2024-10-22
基本概念
Singleton 是一種創(chuàng)立性模型,它用來確保只發(fā)生一個實例,并供給一個訪問它的大局訪問點.對一些類來說,確保只要一個實例是很重要的,比方有的時候,數(shù)據(jù)庫銜接或 Socket 銜接要遭到一定的約束,必須保持同一時間只能有一個銜接的存在.再舉個比如,調(diào)集中的 set 中不能包含重復(fù)的元素,添加到set里的目標必須是僅有的,假如重復(fù)的值添加到 set,它只承受一個實例.JDK中正式運用了Singleton形式來完成 set 的這一特性,我們能夠檢查java.util.Collections里的內(nèi)部靜態(tài)類SingletonSet的原代碼.其實Singleton是簡單但也是應(yīng)用廣泛的形式之一,在 JDK 中隨處可見.
簡單分析
為了完成 Singleton 形式,咱們需要的是一個靜態(tài)的變量,能夠在不創(chuàng)立目標的情況下回憶是否現(xiàn)已發(fā)生過實例了.靜態(tài)變量或靜態(tài)方法都能夠在不發(fā)生詳細實例的情況下直接調(diào)用,這樣的變量或方法不會由于類的實例化而有所改動.在圖1的結(jié)構(gòu)中能夠看到,uniqueInstance 便是這個獨立的靜態(tài)變量,它能夠回憶目標是否現(xiàn)已實例化了,在靜態(tài)方法 Instance 中對這個變量進行判別,若沒有實例化過就發(fā)生一個新的目標,假如現(xiàn)已實例化了則不再發(fā)生新的目標,仍然返回曾經(jīng)發(fā)生的實例.
詳細施行
完成 Singleton 形式的方法通常有三種.
一. 用靜態(tài)方法完成 Singleton 這種方法是使用靜態(tài)方法來監(jiān)督實例的創(chuàng)立.為了避免創(chuàng)立一個以上的實例,咱們好把結(jié)構(gòu)器聲明為 private.
這樣能夠避免客戶程序員經(jīng)過除由咱們供給的方法之外的恣意方法來創(chuàng)立一個實例,假如不把結(jié)構(gòu)器聲明為private,編譯器就會自作聰明的自動同步一個默認的friendly結(jié)構(gòu)器.這種完成方法是常見的,也便是圖1中結(jié)構(gòu)的規(guī)范完成.
singletonTest運行結(jié)果是:
Creating one instance
Creating two instance
Only one instance allowed
能夠看出,第一個實例順利創(chuàng)立,第二個實例創(chuàng)立實拋出了咱們自定義的異常.
三. 用注冊器機制來創(chuàng)立 Singleton 首先用調(diào)集中的Hashtable 和Enumeration來完成addItem(Object key, Object value),getItem(Object key), ,removeItem(Object key)等方法完成一個辦理器,將key和value逐個關(guān)聯(lián)起來,客戶程序員創(chuàng)立實例前首先用addItem方法進行注冊,再用getItem方法獲取實例.Hashtable中的key是僅有的,從而確保創(chuàng)立的實例是僅有的,詳細完成限于篇幅不再細說,在Prototype模型的應(yīng)用一文中我將會給出一個完成注冊器的代碼.用注冊器機制來創(chuàng)立 Singleton形式的優(yōu)點是易于辦理,能夠同時控制多個不同類型的Singleton 實例.
小結(jié)
Singleton形式能夠方便的進行擴充,發(fā)生指定數(shù)目的實例.
在The Design Patterns Java Companion 一書中曾提到過用靜態(tài)類的方法來完成 Singleton形式,并指出java.lang.Math便是一個比如,這兒我并不表明贊同,由于Math并不是一個真正的目標,咱們僅僅直接調(diào)用Math類所包裝的靜態(tài)方法而已,根本就沒有創(chuàng)立實例的過程,又從何說起只發(fā)生一個實例呢?這個問題我曾到Javaranch的論壇上發(fā)過帖子,所有回帖的人也都是對這一觀點持否定態(tài)度.
在多線程的程序中,singleton可能會變的不可靠,可能會出現(xiàn)多個實例,解決的方法很簡單,加個同步修飾符: public static synchronized Singleton getInstance(). 這樣就確保了線程的安全性.
后要說的是我們可能會看見一些其他完成Singleton形式的方法,由于形式在詳細的應(yīng)用時是靈活的,不是一成不變的,并沒有一個固定的做法,但大都是上面幾種方法的變形.但也要注意單例模式可能會帶來一些問題,如測試困難、可能會隱藏不良的設(shè)計等,在使用時需要根據(jù)具體情況進行權(quán)衡。