設計模式-建立型模式-單例
阿新 • • 發佈:2018-11-06
單例模式保證一個類只有一個物件,並且提供一個訪問該例項的全域性訪問點。
1.單例模式例項一(餓漢式)
public class Singleton {
private static Singleton sin = new Singleton(); /// 直接初始化一個例項物件
private Singleton() { /// private型別的建構函式,保證其他類物件不能直接new一該物件的例項
}
public static Singleton getSin() { /// 該類唯一的一個public方法
return sin;
}
}
上述程式碼中的一個缺點是該類載入的時候就會直接
2單例模式例項二(懶漢式)
public class Singleton { private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { // 對獲取例項的方法進行同步 if (instance == null) instance = new Singleton(); return instance; } }
3單例模式例項三(雙重同步鎖,不推薦可能有問題)
public class Singleton { private static Singleton instance; private Singleton (){ } public static Singleton getInstance(){ //對獲取例項的方法進行同步 if (instance == null){ synchronized(Singleton.class){ if (instance == null) instance = new Singleton(); } } return instance; } }
這裡面的疑問可能是為什麼要做兩次判斷和鎖定Singleton.class。
問題一:兩個執行緒同時訪問,當執行緒A的執行緒B同時訪問,都獲得instance是null,只有一個執行緒可以鎖定Singleton.class,假設A執行完畢,獲得物件,B被喚醒在進行訪問時不判斷一次,那麼就new 出了一個新物件。
問題二:因為是靜態方法,所以它只有class可以鎖定,沒有this鎖定。
4.單例模式例項四(使用靜態內部類)
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return Inner.s;
}
private static class Inner{
static Singleton s = new Singleton();
}
}
你可能認為這與第一種相同,焦點在於是不是延遲載入,靜態內部類對於外部成員只有在第一次呼叫時才被載入。
破解單例模式(不能破解列舉單例)
單例模式可以通過反射或反序列化進行破解
舉例程式碼如下
Class clazz = (Class) Class.forName("com.singleton.Singleton");
Constructor<Singleton> con = clazz.getDeclaredConstructor(null);
con.setAccessible(true);//跳過許可權檢查
Singleton s = con.newInstance(null);
System.out.println(s);