轉載地址: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 單例模式的優缺點分析
優點:客戶端使用單例模式的實例的時候,只需要調用一個單一的方法即可生成一個唯一的實例,有利於節約資源。
缺點:首先單例模式很難實現序列化,這就導致採用單例模式的類很難被持久化,當然也很難通過網絡傳輸;其次由於單例採用靜態方法,無法在繼承結構中使用。