你好!今天,我們將從 Java 單例模式開始,深入探討各種設計模式的細節。讓我們回顧一下:我們對設計模式一般了解多少?設計模式是我們可以用來解決許多已知問題的最佳實踐。設計模式通常不依賴於任何編程語言。將它們視為一組建議,以幫助您避免錯誤並避免重新發明輪子。
Java中的單例是什麼?
單例模式是最簡單的類級設計模式之一。有時人們會說“這個類是單例的”,這意味著該類實現了單例設計模式。有時需要編寫一個類,我們將實例化限制為單個對象。例如,一個類負責記錄或連接到一個數據庫。單例設計模式描述了我們如何實現這一點。單例是一種做兩件事的設計模式:-
它保證永遠只有一個類的實例。
-
它提供對該實例的單點全局訪問。
-
私有構造函數。這限制了在類本身之外創建類對象的能力。
-
返回類實例的公共靜態方法。此方法稱為getInstance。這是對類實例的全局訪問點。
實施方案
單例設計模式以各種方式應用。每個選項都以其自己的方式是好的和壞的。一如既往,這裡沒有完美的選擇,但我們應該爭取一個。首先,讓我們決定好與壞的構成,以及影響我們如何評估設計模式的各種實現的指標。讓我們從好的開始。以下是使實施更具吸引力和吸引力的因素:-
惰性初始化:直到需要時才創建實例。
-
簡單透明的代碼:這個指標當然是主觀的,但它很重要。
-
線程安全:在多線程環境下正確運行。
-
多線程環境中的高性能:共享資源時很少或沒有線程阻塞。
-
沒有惰性初始化:當應用程序啟動時加載類,無論是否需要它(矛盾的是,在 IT 世界中,惰性更好)
-
複雜且難以閱讀的代碼。這個指標也是主觀的。如果您的眼睛開始流血,我們會假設實施不是最好的。
-
缺乏線程安全。換句話說,“線程危險”。多線程環境下的錯誤操作。
-
多線程環境下的性能不佳:線程在共享資源時一直或經常相互阻塞。
代碼
現在我們準備好考慮各種實施方案並指出優缺點:簡單的
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
最簡單的實現。優點:
-
簡單透明的代碼
-
線程安全
-
多線程環境下的高性能
- 沒有惰性初始化。
延遲初始化
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
優點:
-
延遲初始化。
-
不是線程安全的
同步訪問
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
優點:
-
延遲初始化。
-
線程安全
-
多線程性能差
雙重檢查鎖定
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
優點:
-
延遲初始化。
-
線程安全
-
多線程環境下的高性能
-
Java 1.5 以下的早期版本不支持(從 1.5 版本開始固定使用 volatile 關鍵字)
班級持有人
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
優點:
-
延遲初始化。
-
線程安全。
-
多線程環境下的高性能。
-
正確的操作需要保證單例對象的初始化沒有錯誤。否則,對getInstance方法的第一次調用將導致ExceptionInInitializerError,所有後續調用將產生NoClassDefFoundError。
單例模式的優缺點
通常,單身人士會完全按照預期進行操作:-
它保證永遠只有一個類的實例。
-
它提供對該實例的單點全局訪問。
-
單例違反了單一職責原則:單例類除了直接的職責外,還控制著實例的數量。
-
普通類對單例的依賴在類的公共契約中是不可見的。
-
全局變量不好。最終,單例會變成一個龐大的全局變量。
-
單例的存在降低了整個應用程序的可測試性,尤其是使用單例的類。