隨筆 - 71  文章 - 15  trackbacks - 0
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          因?yàn)榭诳剩系蹌?chuàng)造了水;
          因?yàn)楹诎担系蹌?chuàng)造了火;
          因?yàn)槲倚枰笥眩陨系圩屇銇?lái)到我身邊
          Click for Shaanxi xi'an, Shaanxi Forecast
          ╱◥█◣
            |田|田|
          ╬╬╬╬╬╬╬╬╬╬╬
          If only I have such a house!
          〖總在爬山 所以艱辛〗
          Email:myesjoy@yahoo.com.cn
          NickName:yesjoy
          MSN:myesjoy@hotmail.com
          QQ:150230516

          〖總在尋夢(mèng) 所以苦痛〗

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          Hibernate在線

          Java友情

          Java認(rèn)證

          linux經(jīng)典

          OA系統(tǒng)

          Spring在線

          Structs在線

          專家專欄

          企業(yè)信息化

          大型設(shè)備共享系統(tǒng)

          工作流

          工作流產(chǎn)品

          網(wǎng)上購(gòu)書

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          概要
          單例模式是最簡(jiǎn)單的設(shè)計(jì)模式之一,但是對(duì)于Java的開發(fā)者來(lái)說(shuō),它卻有很多缺陷。在本月的專欄中,David Geary探討了單例模式以及在面對(duì)多線程(multithreading)、類裝載器(classloaders)和序列化(serialization)時(shí)如何處理這些缺陷。

          單例模式適合于一個(gè)類只有一個(gè)實(shí)例的情況,比如窗口管理器,打印緩沖池和文件系統(tǒng),它們都是原型的例子。典型的情況是,那些對(duì)象的類型被遍及一個(gè)軟件系統(tǒng)的不同對(duì)象訪問(wèn),因此需要一個(gè)全局的訪問(wèn)指針,這便是眾所周知的單例模式的應(yīng)用。當(dāng)然這只有在你確信你不再需要任何多于一個(gè)的實(shí)例的情況下。
          單例模式的用意在于前一段中所關(guān)心的。通過(guò)單例模式你可以:

        1. 確保一個(gè)類只有一個(gè)實(shí)例被建立
        2. 提供了一個(gè)對(duì)對(duì)象的全局訪問(wèn)指針
        3. 在不影響單例類的客戶端的情況下允許將來(lái)有多個(gè)實(shí)例

          盡管單例設(shè)計(jì)模式如在下面的圖中的所顯示的一樣是最簡(jiǎn)單的設(shè)計(jì)模式,但對(duì)于粗心的Java開發(fā)者來(lái)說(shuō)卻呈現(xiàn)出許多缺陷。這篇文章討論了單例模式并揭示了那些缺陷。
          注意:你可以從Resources下載這篇文章的源代碼。

          單例模式


          在《設(shè)計(jì)模式》一書中,作者這樣來(lái)敘述單例模式的:確保一個(gè)類只有一個(gè)實(shí)例并提供一個(gè)對(duì)它的全局訪問(wèn)指針。
          下圖說(shuō)明了單例模式的類圖。
          (圖1)

          單例模式的類圖

          正如你在上圖中所看到的,這不是單例模式的完整部分。此圖中單例類保持了一個(gè)對(duì)唯一的單例實(shí)例的靜態(tài)引用,并且會(huì)從靜態(tài)getInstance()方法中返回對(duì)那個(gè)實(shí)例的引用。
          例1顯示了一個(gè)經(jīng)典的單例模式的實(shí)現(xiàn)。
          例1.經(jīng)典的單例模式
          1. public class ClassicSingleton {
          2.    private static ClassicSingleton instance = null;
          3.    protected ClassicSingleton() {
          4.       // Exists only to defeat instantiation.
          5.    }
          6.    public static ClassicSingleton getInstance() {
          7.       if(instance == null) {
          8.          instance = new ClassicSingleton();
          9.       }
          10.       return instance;
          11.    }
          12. }

          在例1中的單例模式的實(shí)現(xiàn)很容易理解。ClassicSingleton類保持了一個(gè)對(duì)單獨(dú)的單例實(shí)例的靜態(tài)引用,并且從靜態(tài)方法getInstance()中返回那個(gè)引用。
          關(guān)于ClassicSingleton類,有幾個(gè)讓我們感興趣的地方。首先,ClassicSingleton使用了一個(gè)眾所周知的懶漢式實(shí)例化去創(chuàng)建那個(gè)單例類的引用;結(jié)果,這個(gè)單例類的實(shí)例直到getInstance()方法被第一次調(diào)用時(shí)才被創(chuàng)建。這種技巧可以確保單例類的實(shí)例只有在需要時(shí)才被建立出來(lái)。其次,注意ClassicSingleton實(shí)現(xiàn)了一個(gè)protected的構(gòu)造方法,這樣客戶端不能直接實(shí)例化一個(gè)ClassicSingleton類的實(shí)例。然而,你會(huì)驚奇的發(fā)現(xiàn)下面的代碼完全合法:
          1. public class SingletonInstantiator { 
          2.   public SingletonInstantiator() { 
          3.    ClassicSingleton instance = ClassicSingleton.getInstance();
          4. ClassicSingleton anotherInstance =
          5. new ClassicSingleton();
          6.        ... 
          7.   } 
          8. }

          前面這個(gè)代碼片段為何能在沒(méi)有繼承ClassicSingleton并且ClassicSingleton類的構(gòu)造方法是protected的情況下創(chuàng)建其實(shí)例?答案是protected的構(gòu)造方法可以被其子類以及在同一個(gè)包中的其它類調(diào)用。因?yàn)镃lassicSingleton和SingletonInstantiator位于相同的包(缺省的包),所以SingletonInstantiator方法能創(chuàng)建ClasicSingleton的實(shí)例。
          這種情況下有兩種解決方案:一是你可以使ClassicSingleton的構(gòu)造方法變化私有的(private)這樣只有ClassicSingleton的方法能調(diào)用它;然而這也意味著ClassicSingleton不能有子類。有時(shí)這是一種很合意的解決方法,如果確實(shí)如此,那聲明你的單例類為final是一個(gè)好主意,這樣意圖明確,并且讓編譯器去使用一些性能優(yōu)化選項(xiàng)。另一種解決方法是把你的單例類放到一個(gè)外在的包中,以便在其它包中的類(包括缺省的包)無(wú)法實(shí)例化一個(gè)單例類。
          關(guān)于ClassicSingleton的第三點(diǎn)感興趣的地方是,如果單例由不同的類裝載器裝入,那便有可能存在多個(gè)單例類的實(shí)例。假定不是遠(yuǎn)端存取,例如一些servlet容器對(duì)每個(gè)servlet使用完全不同的類裝載器,這樣的話如果有兩個(gè)servlet訪問(wèn)一個(gè)單例類,它們就都會(huì)有各自的實(shí)例。
          第四點(diǎn),如果ClasicSingleton實(shí)現(xiàn)了java.io.Serializable接口,那么這個(gè)類的實(shí)例就可能被序列化和復(fù)原。不管怎樣,如果你序列化一個(gè)單例類的對(duì)象,接下來(lái)復(fù)原多個(gè)那個(gè)對(duì)象,那你就會(huì)有多個(gè)單例類的實(shí)例。
          最后也許是最重要的一點(diǎn),就是例1中的ClassicSingleton類不是線程安全的。如果兩個(gè)線程,我們稱它們?yōu)榫€程1和線程2,在同一時(shí)間調(diào)用ClassicSingleton.getInstance()方法,如果線程1先進(jìn)入if塊,然后線程2進(jìn)行控制,那么就會(huì)有ClassicSingleton的兩個(gè)的實(shí)例被創(chuàng)建。

          正如你從前面的討論中所看到的,盡管單例模式是最簡(jiǎn)單的設(shè)計(jì)模式之一,在Java中實(shí)現(xiàn)它也是決非想象的那么簡(jiǎn)單。這篇文章接下來(lái)會(huì)揭示Java規(guī)范對(duì)單例模式進(jìn)行的考慮,但是首先讓我們近水樓臺(tái)的看看你如何才能測(cè)試你的單例類。

          未完待續(xù)。
        4. posted on 2006-02-14 15:32 ★yesjoy★ 閱讀(230) 評(píng)論(0)  編輯  收藏 所屬分類: 設(shè)計(jì)模式
          主站蜘蛛池模板: 含山县| 延寿县| 霍城县| 犍为县| 泾阳县| 静安区| 柳林县| 合江县| 马边| 锡林浩特市| 洛隆县| 鲁山县| 西安市| 泽库县| 桐庐县| 阿巴嘎旗| 新密市| 琼海市| 开平市| 荥经县| 黄龙县| 临武县| 宁德市| 廊坊市| 南皮县| 泽库县| 沅江市| 临西县| 秦安县| 舟曲县| 宁都县| 阿克陶县| 鹤峰县| 叶城县| 锡林浩特市| 江安县| 北宁市| 河南省| 邛崃市| 长武县| 伽师县|