破壞單例模式的三種方法(執行緒安全情況下)
單例模式有 3 個特點:
單例類只有乙個例項物件;
該單例物件必須由單例類自行建立;
單例類對外提供乙個訪問該單例的全域性訪問點。
單例模式的優點和缺點:
單例模式的優點:
單例模式可以保證記憶體裡只有乙個例項,減少了記憶體的開銷。
可以避免對資源的多重占用。
單例模式設定全域性訪問點,可以優化和共享資源的訪問。
單例模式的缺點:
單例模式一般沒有介面,擴充套件困難。如果要擴充套件,則除了修改原來的**,沒有第二種途徑,違背開閉原則。
在併發測試中,單例模式不利於**除錯。在除錯過程中,如果單例中的**沒有執行完,也不能模擬生成乙個新的物件。
單例模式的功能**通常寫在乙個類中,如果功能設計不合理,則很容易違背單一職責原則。
public
class
lazysingleton
public
static lazysingleton getinstance()
}}return instance;
}}
/**
* 執行緒安全
* 不足之處
* 1、不管是否使用該物件都會建立物件占用記憶體資源
* 2、建立的物件不可變
*/public
class
hungrysingleton
public
static hungrysingleton getinstance()
}
public object clone()
throws clonenotsupportedexception
利用反射可以訪問單例物件的私有構造方法,生成新的物件破壞單例模式。
解決方法:
設定乙個標誌,修改私有建構函式。
private
static
boolean isfirst =
true;if
(isfirst)}}
else
仍然有缺陷,反射可以修改isfirst的值。
懶漢式中如果反射先構造則全域性訪問點將無法訪問.
將單例物件序列化再反序列化時,反序列化的物件與單例物件不是同乙個物件。
解決方法:
加入readresolve()這個方法.
private object readresolve()
使用列舉的方法可以規避反射,序列化,轉殖破壞單例模式
列舉的私有構造方法不能被反射使用,反射無法找到該方法。
列舉不能實現clone方法,所以列舉不能被轉殖
列舉沒有序列化id,但是被反序列化時,與原來的單例物件是同乙個物件。
public
enum singleton
單例設計模式 序列化破壞單例模式?
1 問題猜想,假如將乙個物件通過序列化放到乙個檔案後,再取出來看是否與本身相等?public class hungrysingleton implements serializable private hungrysingleton public static hungrysingleton get...
readResolve 解決反射破壞單例
具體的操作和測試在單例的部落格中都有提到 單例模式的幾種寫法 單例的寫法和測試結果此片文章不再演示,直接去找readresolve 是怎樣防止破壞單例的。在測試 中用到了 objectinputstream 進入到這個 中,找到 片段 走到readobject 方法中。在readobject 方法中...
附 單例模式的破壞
序列化物件對單例模式的破壞與恢復 首先這是乙個餓漢式的單例物件構建方式,一般情況下獲取到的都是同乙個單例物件 但是當序列化寫入本地再讀入記憶體時,會重新建立乙個單例物件 為什麼會在讀入序列化後的物件時會讓單例模式失效呢?這兒從readobject 方法入手 進入這個方法後 private 進入pri...