單例模式的第一個版本,一般都是采用“餓漢式”的模式,即在類加載進來的時候就實例化對象,但是這種方式比較消耗計算機資源
具體如下demo:
package cn.design.singleton;
public class Singleton {
private String name;
//在類被加載進入內存的時候就創建單一的對象
public static final Singleton instance=new Singleton();
private Singleton() {//構造方法私有化
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//提供一個全局的靜態方法
public static Singleton getInstance() {
return instance;
}
}
如是出現了單例的第二個版本:“懶漢式”,在單線程下工作的還不錯,但在多線程下存在安全性問題,具體如下demo:
package cn.design.singleton;
public class Singleton {
private String name;
private static Singleton instance;//對單例本身引用的名稱
private Singleton() {//構造方法私有化
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//提供一個全局的靜態方法
public static Singleton getInstance() {
if (null == instance) {
instance = new Singleton();
}
return instance;
}
}
考慮到在多線程下,懶漢模式不適用,如是采用了對方法進行同步的方式,出現了第三個版本的單例,具體如下:
package cn.design.singleton;
public class Singleton {
private String name;
private static Singleton instance;//對單例本身引用的名稱
private Singleton() {//構造方法私有化
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//提供一個全局的靜態方法
public static synchronized Singleton getInstance() {
if (null == instance) {
instance = new Singleton();
}// if
return instance;
}
}
但第三個版本的singleton比較浪費資源,每次都要進行同步檢查,事實上第一次進行同步檢查就可以了,如是出現了第四個比較成熟的單例模式,如下:
package cn.design.singleton;
public class Singleton {
private String name;
private static Singleton instance;//對單例本身引用的名稱
private Singleton() {//構造方法私有化
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
//提供一個全局的靜態方法
public static Singleton getInstance() {
if (null == instance) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}// if
return instance;
}
}
測試代碼如下:
package cn.design.singleton;
public class TestSingleton {
public static void main(String[] args) {
//實例化對象
Singleton singleton1=Singleton.getInstance();
Singleton singleton2=Singleton.getInstance();
//賦值
singleton1.setName("Jon");
singleton2.setName("Linda");
System.out.println(singleton1.getName());
System.out.println(singleton2.getName());
}
}
輸出結果為:
Linda
Linda
單例的優點:實例化的時候,只需要調用一個單一的方法即可實現唯一的實例,有利於節約資源
缺點:首先很難實現序列化,其次由於單例采用靜態方法,無法在繼承結構中使用