設計模式之單例模式(二)
阿新 • • 發佈:2018-12-16
單例模式
顧名思義,單例模式就是保證某個類只有一個例項。在計算機系統中,執行緒池、快取、日誌物件、對話方塊、印表機、顯示卡的驅動程式物件常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機中。每臺計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免一個通訊埠同時被兩個請求同時呼叫。
1.餓漢模式
public class HungrySingleton { //構造器私有化 private HungrySingleton(){} private static HungrySingleton singleton = new HungrySingleton(); //靜態工廠方法返回實體類 public static HungrySingleton getInstance(){ return singleton; } }
Singleton通過將構造方法限定為private避免了類在外部被例項化,在同一個虛擬機器範圍內,Singleton的唯一例項只能通過getInstance()方法訪問。
測試:
public class test { public static void main(String[] args) { //得到實體 HungrySingleton singleton1 = HungrySingleton.getInstance(); HungrySingleton singleton2 = HungrySingleton.getInstance(); System.out.println("singleton1:"+singleton1); System.out.println("singleton2:"+singleton2); } }
輸出結果:
可以看見是相同的控制代碼
但是!!!!!我們可以用反射生成構造私有化的類。如下:
public class test1 { public static void main(String[] args) { try { //反射獲取類 Class c1 =Class.forName("design.singleton.HungrySingleton"); Constructor[] constructors = c1.getDeclaredConstructors(); //將構造器的Accessible設定為true AccessibleObject.setAccessible(constructors, true); //反射獲得兩個實體 for (Constructor constructor:constructors){ if(constructor.isAccessible()){ HungrySingleton singleton = (HungrySingleton)constructor.newInstance(); System.out.println("singleton1:"+singleton); } } for (Constructor constructor:constructors){ if(constructor.isAccessible()){ HungrySingleton singleton = (HungrySingleton)constructor.newInstance(); System.out.println("singleton1:"+singleton); } } } catch (Exception e) { e.printStackTrace(); } } }
結果為:
表明其生成了兩個例項,所以單例模式是不考慮反射的情況下是單例模式。
2.懶漢模式
public class LazySingleton {
// 私有構造
private LazySingleton() {}
private static LazySingleton single = null;
public static LazySingleton getInstance() {
if(single == null){
single = new LazySingleton();
}
return single;
}
}
懶漢模式在多執行緒中可能出現多個實體,所以使用時應該注意可以通過加類鎖,確保執行緒安全。