在23種設計模式中單利模式算是比較簡單的一種設計模式了,雖然簡單,但是他的實現卻有很多種。下面會給出兩種最佳實現和其他一些常見的實現方式。
單元素列舉
不需要延遲載入時的最佳實現
public enum Singleton {
//每個元素就是一個單例
INSTANCE;
//業務方法
public void method(){}
}
複製程式碼
優點:
- 能防止反射
- 能防序列化
- 執行緒安全
- 呼叫效率高
缺點:
- 不能延時載入
靜態內部類
需要延遲載入時的最佳實現
public class Singleton {
//1. 建立私有的 靜態內部類
private static class inner {
//1.1 在靜態內部類裡,建立 私有的 靜態的 外部類物件
private static Singleton instance = new Singleton();
}
//2. 私有化構造器,禁止他人建立例項
private Singleton() {
}
//3. 建立 公開的 靜態的 獲取例項的方法
public static Singleton getInstance() {
return inner.instance;
}
}
複製程式碼
優點:
- 執行緒安全
- 呼叫效率高
- 能延時載入
缺點:
- 不能能防止反射
- 不能防序列化
餓漢式
public class Singleton {
//1. 建立私有的 靜態的內部例項
private static Singleton instance = new Singleton();
//2. 私有化構造器,禁止他人建立例項
private Singleton(){}
//3. 建立 公開的 靜態的 獲取例項的方法
public static Singleton getInstance(){
return instance;
}
}
複製程式碼
優點:
- 執行緒安全
- 呼叫效率高
缺點:
- 不能能防止反射
- 不能防序列化
- 不能延時載入
懶漢式
public class Singleton {
//1. 建立私有的 靜態的內部例項,並初始化為null
private static Singleton instance = null;
//2. 私有化構造器,禁止他人建立例項
private Singleton() {
}
//3. 建立 公開的 靜態的 獲取例項的方法
public static Singleton getInstance() {
// 先判斷單例是否為空,以避免重複建立
if( instance == null){
instance = new Singleton();
}
return instance;
}
}
複製程式碼
優點:
- 能延時載入 缺點:
- 不能能防止反射
- 不能防序列化
- 執行緒不安全
- 呼叫效率不高
懶漢式 + 同步鎖
public class Singleton {
//1. 建立私有的 靜態的內部例項,並初始化為null
private static Singleton instance = null;
//2. 私有化構造器,禁止他人建立例項
private Singleton() {
}
//3. 建立 公開的 靜態的 獲取例項的方法
public static synchronized Singleton getInstance() {
// 加入同步鎖
if (instance == null)
instance = new Singleton();
return instance;
}
}
複製程式碼
優點:
- 能延時載入
- 執行緒安全 缺點:
- 不能能防止反射
- 不能防序列化
- 呼叫效率不高
雙重校驗鎖(懶漢式的改進)
注意:JVM的指令重排序,可能會導致雙重校驗鎖失效
public class Singleton {
//1. 建立私有的 靜態的內部例項,並初始化為null
private static Singleton instance = null;
//2. 私有化構造器,禁止他人建立例項
private Singleton() {
}
//3. 建立 公開的 靜態的 獲取例項的方法
public static Singleton getInstance() {
// 加入雙重校驗鎖
// 校驗鎖1:第1個if
if( instance == null){
synchronized (Singleton.class){
// 校驗鎖2:第2個 if
if( instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
複製程式碼
優點:
- 能延時載入
- 執行緒安全 缺點:
- 不能能防止反射
- 不能防序列化
- 呼叫效率不高
雙重校驗鎖優化(規避指令重排序的影響)
使用 volatile 關鍵字來防止指令重排序
public class Singleton {
//1. 建立私有的 靜態的 可見的 內部例項,並初始化為null
private static volatile Singleton instance = null;
//2. 私有化構造器,禁止他人建立例項
private Singleton() {
}
//3. 建立 公開的 靜態的 獲取例項的方法
public static Singleton getInstance() {
// 加入雙重校驗鎖
// 校驗鎖1:第1個if
if( instance == null){
synchronized (Singleton.class){
// 校驗鎖2:第2個 if
if( instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
複製程式碼
優點:
- 能延時載入
- 執行緒安全 缺點:
- 不能能防止反射
- 不能防序列化
- 呼叫效率不高