1.單例模式的定義
確定某一個類隻有一個執行個體,而且自行執行個體化并向整個系統提供這個執行個體。
2.單例模式通用類型

單例模式通用類型
Singleton類稱為單例類,通過使用private的構造函數確定了應用中隻産生一個執行個體。
單例模式通用代碼
public class Singleton{
private static final Singleton singleton=new Singleton();
//限制産生多個對象
private Singleton(){
}
//通過該方法擷取執行個體
public static Singleton getSingleton(){
return singleton;
}
}
3.單例模式其他常用實作方式
3.1 餓漢式(線程安全)
上面的通用模式,也被稱為餓漢式單例
3.2懶漢式(線程不安全)
public class Singleton{
//不加final
private static Singleton singleton=null;
private Singleton(){
}
public static Singleton getSingleton(){
if (single == null) {
//在第一次調用getInstance()時才執行個體化,實作懶加載,是以叫懶漢式
single = new Singleton();
}
return single;
}
}
懶漢式對singleton對定義不能添加final修飾符
聲明為final的變量,必須在類加載完成時已經指派
就是,如果你是final非static成員,必須在構造器或者代碼塊或者直接定義指派;
如果是final static 成員變量,必須直接指派或者靜态代碼塊中指派。
3.3懶漢式(線程安全)
public class Singleton {
private Singleton() {
}
private static Singleton single = null;
//加上synchronized
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
相比于不安全的懶漢式,就是加了一個類鎖
3.4DCL模式(雙重檢查鎖定模式)
public class Singleton {
private volatile static Singleton singleton=null;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
volatile關鍵字能夠保證可見性,被volatile修飾的變量,在一個線程中被改變時會立刻同步到主記憶體中,而另一個線程在操作這個變量時都會先從主記憶體更新這個變量的值。不過DCL中添加volatile最主要的應該是為了抑制重排序。如果隻是單單的可見行,隻加鎖也是能解決問題的。
關于類鎖,對象鎖的問題自行百度吧
3.5靜态内部類單例模式
public class SingleTon {
private SingleTon() {
}
public SingleTon getInstance(){
return SingleTonHolder.singleton;
}
private static class SingleTonHolder{
private static final SingleTon singleton=new SingleTon();
}
}
靜态内部類單例的寫法,當第一次類加載當時候,并不會導緻初始化singleton,隻有在第一次調用getInstance的時候才會初始化。
這種寫法不僅能保證線程安全、單例對象的唯一性,同時也延遲類單例的執行個體化。
3.6枚舉單例
public enum SingleTonA {
SINGLETONA;
//添加自己需要的操作
public void method(){
}
}
對于枚舉。。。隻記得剛開始入門的時候忘記從哪裡看到一句,Android中盡量少用枚舉,,,然後我就從來沒有關注過枚舉了,不過在單例的幾種寫法中,枚舉是最安全的寫法。其他寫法通過反射或者反序列化,都可能會導緻單例失效,但是枚舉單例這種寫法不會(原因是因為jdk内部實作的,當建立對象,如果判斷出是枚舉類型,則不會重新建立)。但是就我個人而言。。。可能是思想定勢把,不愛用這個。。
4.使用單例模式可能會出現的洩漏問題
context洩漏
view洩漏
對于context洩漏,比如單例執行個體化的過程中,傳入了一個activity的context,然後界面退出了,但是單例并沒有銷毀,則這個單例持有着activity的context,導緻activity無法回收。解決方法可以傳入application的context,或者在該activity退出的時候,置null。
對于view的洩漏,則可以使用弱引用,或同上置null