設計模式之單例模式

轉載地址:http://stormzhang.github.io/designpatterns/2013/05/01/singleton/

1 單例模式解釋

單例模式是一種對象創建性模式,使用單例模式,可以保證爲一個類只生成唯一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。

單例模式的要點有三個:一是某個類只能有一個實例;而是必須自行創建整個實例;三是它必須自行向整個系統提供整個實例。

英文定義爲:Ensure a class only has one instance, and provide a global point of access to it.

2 單例模式深入分析

單例模式適合一個類只有一個實例的情況, 比如窗口管理器,打印緩衝池和文件系統,它們都是原型的例子。典型的情況是,那些對象的類型被遍及一個軟件系統的不同對象訪問,因此需要一個全局的訪問指針,這便是總所周知的單例模式的應用。當然這只有在你確信你不再需要任何多於一個的實例的情況下。

3 使用場景及代碼實現

下面就舉例來說明下:

單例模式的第一個版本,“餓漢式”,也就是當類加載進來的就立即實例化對象,但是這種方式比較的消耗計算機資源。如下:

public class Foo {
    // 在類被加載進入內存的時候就創建單一的Foo對象
    public static final Foo foo = new Foo();

    // 構造函數私有化
    private Foo() {

    }

    // 提供一個全局的靜態方法
    public static Foo getFoo() {
        return foo;
    }
}

單例模式的第二個版本,“懶漢式”,在單線程下能夠非常好的工作,但是在多線程下存在線程安全問題,如下:

// 這種方式在需要使用的時候才實例化
public class Foo {
    private static Foo foo;

    // 構造函數私有化
    private Foo() {

    }

    // 提供一個全局的靜態方法
    public static Foo getFoo() {
        if (foo == null) {
            foo = new Foo();
        }
        return foo;
    }
}

單例模式的第三個版本,爲解決多線程問題,採用了對函數進行同步的方式,但是比較浪費資源,因爲每次都要進行同步檢查,而實際中真正需要檢查只是第一次實例化的時候,如下:

public class Foo {
    private static Foo foo;

    // 構造函數私有化
    private Foo() {
    }

    // 提供一個全局的靜態方法,使用同步方法
    public static synchronized Foo getFoo() {
        if (foo == null) {
            foo = new Foo();
        }
        return foo;
    }
}

單例模式的第四個版本,既解決了”懶漢式“的多線程問題,又解決了資源浪費的現象,看上去是一種不錯的選擇,如下:

public class Foo {
    private static Foo foo;

    // 構造函數私有化
    private Foo() {
    }

    // 提供一個全局的靜態方法
    public static Foo getFoo() {
        if (foo == null) {
            synchronized (Foo.class) {
                if (foo == null) {
            	    foo = new Foo();
                }
            }
        }
        return foo;
    }
}

4 單例模式的優缺點分析

優點:客戶端使用單例模式的實例的時候,只需要調用一個單一的方法即可生成一個唯一的實例,有利於節約資源。

缺點:首先單例模式很難實現序列化,這就導致採用單例模式的類很難被持久化,當然也很難通過網絡傳輸;其次由於單例採用靜態方法,無法在繼承結構中使用。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章