【設計模式】學習筆記7:單件模式(Singleton)

來源:互聯網
上載者:User
文章目錄
  • 單件模式的經典但簡陋(有問題)的實現:

本文出自   http://blog.csdn.net/shuangde800

走進單件模式

有些對象我們只需要一個,比如:線程池,緩衝,對話方塊,處理喜好設定和註冊表的對象,日誌對象,充當印表機,顯卡等裝置的驅動程式對象等。

這些類的對象只能有一個執行個體,如果有多個,然而會導致許多問題產生。

有人可能覺得,這隻要用全域變數或者靜態變數就可以做到了

這樣做的缺點:

必須程式一開始就建立對象,但是有些對象可能用不到,耗費資源。而單件模式在需要時才建立

單間模式的實現
單件模式的經典但簡陋(有問題)的實現:

把建構函式設定為私人的,再加一個靜態方法用來建立對象並返回。

public Singleton{        private static Sigleton uniqueInstance;    // 構造器是私人的,只有類內部方法才能建立類    private Singleton() { }    public static MyClass getInstance(){        if(uniqueInstance == null){ // 只有是null的才建立對象            uniqueInstance = new Singleton();         }        return uniqueInstance;    }}


上面那個做法,會出現問題,原因是多線程產生的問題。

假如有兩個線程要幾乎同時要建立一個對象,那麼將會發生下面的情況:

看,發現Thread one和Thread two都各自建立了一個對象!

 解決方案1:

把getInstance( )變成同步(synchronized)方法,多線程災難幾乎就可以輕易解決了。

public Singleton{        private static Sigleton uniqueInstance;    // 構造器是私人的,只有類內部方法才能建立類    private Singleton() { }    // 通過增加synchronized關鍵字,會迫使每個線程在進入這個    // 方法之前,要先等候別的線程離開該方法。    // 也就是說,不會有兩個線程可以同時進入這個方法    public static synchronized MyClass getInstance(){        if(uniqueInstance == null){ // 只有是null的才建立對象            uniqueInstance = new Singleton();         }        return uniqueInstance;    }}


缺點: 每次用該方法都要同步,會降低拖垮程式的效能。同步一個方法可能會造成程式執行效率下降100倍。


解決方案2:急切執行個體化
public Singleton{        // 在靜態初始化器(static initializer)中建立單件    // 保證了安全執行緒(thread safe)    private static Sigleton uniqueInstance = new Singleton();    // 構造器是私人的,只有類內部方法才能建立類    private Singleton() { }    public static synchronized MyClass getInstance(){        return uniqueInstance;    }}
解決方案3: 用“雙重檢查加鎖”,在getInstance()中減少使用同步

利用“雙重檢查加鎖”(double-checked locking),首先檢查執行個體是否已經建立了,如果尚未建立,“才”進行同步。

這樣,只有第一次會同步,之後再也不會了

public Singleton{    // 注意這裡加了volatile關鍵字    // volatile關鍵字確保:當uniqueInstance變數被初始化成Singleton執行個體時    // 多個線程正確地處理uniqueInstance變數    private static volatile Sigleton uniqueInstance;    private Singleton() { }    public static synchronized MyClass getInstance() {        if(uniqueInstance == null) {             synchronized (Singleton.class) {                if(uniqueInstance == null){                    uniqueInstance = new Singleton();                 }             }        }        return uniqueInstance;    }}

注意! 雙重檢查加鎖不使用於java 1.4以及更早的版本。

定義單件模式

單件模式確保一個類只有一個執行個體,並提供一個全域訪問點

單件模式的類圖很簡單

全域變數 VS 單件模式

在Java中,全域變數基本上就是對對象的靜態引用。

在這樣的情況下使用全域變數會有一些缺點,我們已經提到了期中一個:急切執行個體化 VS.延遲執行個體化。

但是我們要記住這個模式的目的:確保類只有一個執行個體並提供全域訪問。

全域變數也會變相鼓勵開發人員,用許多全域變數指向許多小對象來造成命名空間(namespace)的汙染。

單件模式不鼓勵這樣的現象,但單件仍然可能被濫用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.