目錄
一、介紹
1.定義
確保類只有一個實例,並提供一個全局訪問點。
2.角色
- Singleton:單例類
3.特點
- 優點:因爲系統內存中只有一個實例,可以節約系統資源,並且減少了因爲創建、銷燬對象帶來的損耗,提高了系統的性能。
- 缺點:該模式沒有抽象層,不易於擴展,且違背了“單一職責原則”,既負責實例的創建,又包含了一些業務方法。
二、實現
1.餓漢式(線程安全)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
在加載類時即創建唯一的單例實例,不管用不用,先創建再說。若一直未被使用,則浪費了空間,但因爲每次調用時無需判斷,節省了運行時間,以空間換時間。
2.懶漢式
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在第一次使用實例時才創建。該方式是線程不安全的,在多個線程同時訪問getInstance方法時會出現問題,可在getInstance方法使用synchronized關鍵字解決該問題。但每次調用該方法時都要先獲取鎖,可能會增加運行時間,還會造成阻塞。
3.懶漢式(雙重檢查加鎖版本)
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
只有在第一次創建實例時纔會進入synchronized塊,減少了getInstance方法的運行時間。同時採用了volatile關鍵字保持數據的可見性以及防止指令重排。
4. 枚舉方式
public enum Singleton {
INSTANCE;
public void doSomething() {
}
}
枚舉創建實例是線程安全的,因此該方法既簡潔又安全,但可讀性不高,較少用。
5.靜態內部類
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
在顯式調用getInstance方法時纔會裝載SingletonHolder類,從而初始化實例,因此是線程安全的。
參考:
1. 《Head First 設計模式》
2. 《圖說設計模式》 https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/singleton.html