<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dict.CN 在線詞典, 英語學(xué)習(xí), 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統(tǒng)計

    留言簿(23)

    積分與排名

    優(yōu)秀學(xué)習(xí)網(wǎng)站

    友情連接

    閱讀排行榜

    評論排行榜

    Java模式設(shè)計之單例模式

    作為對象的創(chuàng)建模式[GOF95], 單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統(tǒng)提供這個實例。這個類稱為單例類。
    注:本文乃閻宏博士的《Java與模式》一書的第十五章。

      引言

      單例模式的要點

      單例單例

      顯然單例模式的要點有三個;一是某各類只能有一個實例;二是它必須自行創(chuàng)建這個事例;三是它必須自行向整個系統(tǒng)提供這個實例。在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙" 和"客戶丙"是單例對象的三個客戶對象??梢钥吹?,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。



      資源管理

      一些資源管理器常常設(shè)計成單例模式。

      在計算機系統(tǒng)中,需要管理的資源包括軟件外部資源,譬如每臺計算機可以有若干個打印機,但只能有一個Printer Spooler, 以避免兩個打印作業(yè)同時輸出到打印機中。每臺計算機可以有若干傳真卡,但是只應(yīng)該有一個軟件負(fù)責(zé)管理傳真卡,以避免出現(xiàn)兩份傳真作業(yè)同時傳到傳真卡中的情況。每臺計算機可以有若干通信端口,系統(tǒng)應(yīng)當(dāng)集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調(diào)用。

      需要管理的資源包括軟件內(nèi)部資源,譬如,大多數(shù)的軟件都有一個(甚至多個)屬性(properties)文件存放系統(tǒng)配置。這樣的系統(tǒng)應(yīng)當(dāng)由一個對象來管理一個屬性文件。

      需要管理的軟件內(nèi)部資源也包括譬如負(fù)責(zé)記錄網(wǎng)站來訪人數(shù)的部件,記錄軟件系統(tǒng)內(nèi)部事件、出錯信息的部件,或是對系統(tǒng)的表現(xiàn)進(jìn)行檢查的部件等。這些部件都必須集中管理,不可政出多頭。

      這些資源管理器構(gòu)件必須只有一個實例,這是其一;它們必須自行初始化,這是其二;允許整個系統(tǒng)訪問自己這是其三。因此,它們都滿足單例模式的條件,是單例模式的應(yīng)用。

      一個例子:Windows 回收站

      Windows 9x 以后的視窗系統(tǒng)中都有一個回收站,下圖就顯示了Windows 2000 的回收站。



      在整個視窗系統(tǒng)中,回收站只能有一個實例,整個系統(tǒng)都使用這個惟一的實例,而且回收站自行提供自己的實例。因此,回收站是單例模式的應(yīng)用。

      雙重檢查成例

      在本章最后的附錄里研究了雙重檢查成例。雙重檢查成例與單例模式并無直接的關(guān)系,但是由于很多C 語言設(shè)計師在單例模式里面使用雙重檢查成例,所以這一做法也被很多Java 設(shè)計師所模仿。因此,本書在附錄里提醒讀者,雙重檢查成例在Java 語言里并不能成立,詳情請見本章的附錄。

    單例模式有以下的特點:

       .. 單例類只可有一個實例。

       .. 單例類必須自己創(chuàng)建自己這惟一的實例。

       .. 單例類必須給所有其他對象提供這一實例。

      雖然單例模式中的單例類被限定只能有一個實例,但是單例模式和單例類可以很容易被推廣到任意且有限多個實例的情況,這時候稱它為多例模式(Multiton Pattern) 和多例類(Multiton Class),請見"專題:多例(Multiton )模式與多語言支持"一章。單例類的簡略類圖如下所示。



      由于Java 語言的特點,使得單例模式在Java 語言的實現(xiàn)上有自己的特點。這些特點主要表現(xiàn)在單例類如何將自己實例化上。

      餓漢式單例類餓漢式單例類是在Java 語言里實現(xiàn)得最為簡便的單例類,下面所示的類圖描述了一個餓漢式單例類的典型實現(xiàn)。



      從圖中可以看出,此類已經(jīng)自已將自己實例化。

      代碼清單1:餓漢式單例類

    public class EagerSingleton
    {
    private static final EagerSingleton m_instance =
    new EagerSingleton();
    /**
    * 私有的默認(rèn)構(gòu)造子
    */
    private EagerSingleton() { }
    /**
    * 靜態(tài)工廠方法
    */
    public static EagerSingleton getInstance()
    {

    ·224·Java 與模式
    return m_instance;
    }
    }

      讀者可以看出,在這個類被加載時,靜態(tài)變量m_instance 會被初始化,此時類的私有構(gòu)造子會被調(diào)用。這時候,單例類的惟一實例就被創(chuàng)建出來了。

      Java 語言中單例類的一個最重要的特點是類的構(gòu)造子是私有的,從而避免外界利用構(gòu)造子直接創(chuàng)建出任意多的實例。值得指出的是,由于構(gòu)造子是私有的,因此,此類不能被繼承。

    懶漢式單例類

      與餓漢式單例類相同之處是,類的構(gòu)造子是私有的。與餓漢式單例類不同的是,懶漢式單例類在第一次被引用時將自己實例化。如果加載器是靜態(tài)的,那么在懶漢式單例類被加載時不會將自己實例化。如下圖所示,類圖中給出了一個典型的餓漢式單例類實現(xiàn)。



      代碼清單2:懶漢式單例類

    package com.javapatterns.singleton.demos;
    public class LazySingleton
    {
    private static LazySingleton
    m_instance = null;
    /**
    * 私有的默認(rèn)構(gòu)造子,保證外界無法直接實例化
    */
    private LazySingleton() { }
    /**
    * 靜態(tài)工廠方法,返還此類的惟一實例
    */
    synchronized public static LazySingleton
    getInstance()
    {
    if (m_instance == null)
    {
    m_instance = new LazySingleton();
    }
    return m_instance;
    }
    }

      讀者可能會注意到,在上面給出懶漢式單例類實現(xiàn)里對靜態(tài)工廠方法使用了同步化,以處理多線程環(huán)境。有些設(shè)計師在這里建議使用所謂的"雙重檢查成例"。必須指出的是,"雙重檢查成例"不可以在Java 語言中使用。不十分熟悉的讀者,可以看看后面給出的小節(jié)。

      同樣,由于構(gòu)造子是私有的,因此,此類不能被繼承。餓漢式單例類在自己被加載時就將自己實例化。即便加載器是靜態(tài)的,在餓漢式單例類被加載時仍會將自己實例化。單從資源利用效率角度來講,這個比懶漢式單例類稍差些。

      從速度和反應(yīng)時間角度來講,則比懶漢式單例類稍好些。然而,懶漢式單例類在實例化時, 必須處理好在多個線程同時首次引用此類時的訪問限制問題,特別是當(dāng)單例類作為資源控制器,在實例化時必然涉及資源初始化,而資源初始化很有可能耗費時間。這意味著出現(xiàn)多線程同時首次引用此類的機率變得較大。

      餓漢式單例類可以在Java 語言內(nèi)實現(xiàn), 但不易在C++ 內(nèi)實現(xiàn),因為靜態(tài)初始化在C++ 里沒有固定的順序,因而靜態(tài)的m_instance 變量的初始化與類的加載順序沒有保證,可能會出問題。這就是為什么GoF 在提出單例類的概念時,舉的例子是懶漢式的。他們的書影響之大,以致Java 語言中單例類的例子也大多是懶漢式的。實際上,本書認(rèn)為餓漢式單例類更符合Java 語言本身的特點。


    登記式單例類

      登記式單例類是GoF 為了克服餓漢式單例類及懶漢式單例類均不可繼承的缺點而設(shè)計的。本書把他們的例子翻譯為Java 語言,并將它自己實例化的方式從懶漢式改為餓漢式。只是它的子類實例化的方式只能是懶漢式的, 這是無法改變的。如下圖所示是登記式單例類的一個例子,圖中的關(guān)系線表明,此類已將自己實例化。



      代碼清單3:登記式單例類

    import java.util.HashMap;
    public class RegSingleton
    {
    static private HashMap m_registry = new HashMap();
    static
    {
    RegSingleton x = new RegSingleton();
    m_registry.put( x.getClass().getName() , x);
    }
    /**
    * 保護(hù)的默認(rèn)構(gòu)造子
    */
    protected RegSingleton() {}
    /**
    * 靜態(tài)工廠方法,返還此類惟一的實例
    */
    static public RegSingleton getInstance(String name)
    {
    if (name == null)
    {
    name = "com.javapatterns.singleton.demos.RegSingleton";
    }
    if (m_registry.get(name) == null)
    {
    try
    {
    m_registry.put( name,
    Class.forName(name).newInstance() ) ;
    }
    catch(Exception e)
    {
    System.out.println("Error happened.");
    }
    }
    return (RegSingleton) (m_registry.get(name) );
    }
    /**
    * 一個示意性的商業(yè)方法
    */
    public String about()
    {
    return "Hello, I am RegSingleton.";
    }
    }

      它的子類RegSingletonChild 需要父類的幫助才能實例化。下圖所示是登記式單例類子類的一個例子。圖中的關(guān)系表明,此類是由父類將子類實例化的。



      下面是子類的源代碼。

      代碼清單4:登記式單例類的子類

    import java.util.HashMap;
    public class RegSingletonChild extends RegSingleton
    {
    public RegSingletonChild() {}
    /**
    * 靜態(tài)工廠方法
    */
    static public RegSingletonChild getInstance()
    {
    return (RegSingletonChild)
    RegSingleton.getInstance(
    "com.javapatterns.singleton.demos.RegSingletonChild" );
    }
    /**
    * 一個示意性的商業(yè)方法
    */
    public String about()
    {
    return "Hello, I am RegSingletonChild.";
    }
    }

      在GoF 原始的例子中,并沒有g(shù)etInstance() 方法,這樣得到子類必須調(diào)用的getInstance(String name)方法并傳入子類的名字,因此很不方便。本章在登記式單例類子類的例子里,加入了getInstance() 方法,這樣做的好處是RegSingletonChild 可以通過這個方法,返還自已的實例。而這樣做的缺點是,由于數(shù)據(jù)類型不同,無法在RegSingleton 提供這樣一個方法。由于子類必須允許父類以構(gòu)造子調(diào)用產(chǎn)生實例,因此,它的構(gòu)造子必須是公開的。這樣一來,就等于允許了以這樣方式產(chǎn)生實例而不在父類的登記中。這是登記式單例類的一個缺點。

      GoF 曾指出,由于父類的實例必須存在才可能有子類的實例,這在有些情況下是一個浪費。這是登記式單例類的另一個缺點。












    posted on 2007-05-21 12:33 都市淘沙者 閱讀(133) 評論(0)  編輯  收藏 所屬分類: Java Basic/Lucene/開源資料

    主站蜘蛛池模板: 日本妇人成熟免费中文字幕| 9久热这里只有精品免费| 国产成人精品亚洲2020| 亚洲激情视频网站| 亚洲天堂一区二区三区四区| 亚洲精品91在线| 亚洲精品第五页中文字幕| 久久亚洲精品中文字幕| 亚洲日产2021三区在线| 亚洲人成网男女大片在线播放| 国产成人精品日本亚洲18图| 亚洲欧洲国产综合AV无码久久| 亚洲日本VA午夜在线电影| 怡红院亚洲红怡院在线观看| 精品在线免费视频| 国产日韩AV免费无码一区二区三区 | 日韩精品免费一区二区三区| 日韩免费高清一级毛片在线| 午夜亚洲av永久无码精品| 国产偷窥女洗浴在线观看亚洲 | 88av免费观看| 国产桃色在线成免费视频| 成年女人色毛片免费看| 国产精品成人四虎免费视频| 亚洲一级特黄大片无码毛片| 亚洲国产精品嫩草影院在线观看 | 亚洲国产成人手机在线电影bd| 亚洲人成网网址在线看| 色偷偷噜噜噜亚洲男人| 又硬又粗又长又爽免费看| 七色永久性tv网站免费看| 99无码人妻一区二区三区免费 | 120秒男女动态视频免费| 手机在线免费视频| 亚洲精品无码专区2| 亚洲成色999久久网站| 亚洲另类无码专区首页| 久久www免费人成精品香蕉 | 成人特级毛片69免费观看| 久久久久久AV无码免费网站下载| 99在线视频免费观看视频|