java設計模式--單例模式


在android實際開發中,我們經常會用到一些開源庫,諸如picasso,imageLoader以及okHttp等第三方的開源框架,在這些開源庫中,我們多多少少都會看到單例模式的使用,這里對單例模式做個總結。

單例模式

單例模式,顧名思義就是單例對象的類必須保證只有一個是實例的存在,而且自行實例化並向整個系統提供這個實例。

使用場景

當我們需要確保一個類只有一個對象的場景,避免多個對象消耗過多的資源,如要訪問IO或者數據庫等資源的時候,可以考慮使用這個模式。

單例模式的實現
下面簡單介紹一下單例模式的實現方法:

1.懶漢式單例模式
之所以叫做懶漢單例,是因為我們只需要在我們需要創建這個類的對象的時候才需要進行對這個對象的實例化操作,如下述代碼所示:

public class Singleton{
private static Singleton instance;
private Singleton(){}

public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
}
}

這是最簡單的懶漢式的實現方法,但是這種實現方法有很大的弊端,當我們如果有多個線程訪問這個單例的時候,並不能保證只有一個單例對象。

舉個例子,比如我們有兩個線程A,B同時訪問這個單例,那么A判斷完后發現Instance還沒實例化,就會產生一個單例,恰巧在A判斷的同時B也剛好訪問了,那么B獲得到的信息也是instance==null,那么單例就有兩個對象了

為了防止上述的問題的產生,我們引入sychronized關鍵字,修改后如下:

public class Singleton{
private static Singleton instance;
private Singleton(){}

public static Singleton getInstance(){
if(instance==null){
sychronized(Singleton.class)
if(instance==null)
instance=new Singleton();
}
}
}

通過進行雙重鎖的判斷,我們可以避免多個實例的產生,在getInstance中我們進行兩次的非空判斷。

1.餓漢式單例模式
餓漢單例天生就是線程安全的,我們不必學要進行多余的線程安全的判斷,如下所示:

public class Singleton{
private static Singleton instance=new Singleton();
private Singleton(){}

public static Singleton getInstance(){
return instance;
}
}

由於一開始我們就實例化了這個類,所以天生是線程安全的。


那有沒有更好的方法呢,答案是有的,在《effective java》書中就為我們提供了更加安全的方法:

1.使用內部靜態類實現:

public class Singleton{
private Singleton(){}

public static Singleton getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
priavte static final Singleton instance=new Singleton();
}
}

當我們第一次加載這個類的時候並不會初始化instance,只有在我們第一次調用getInstance才會,因此第一次調用getInstance會導致虛擬機加載SingletonHolder類,這種方式不僅能保證線程安全,也可以保證其唯一性,也延遲了單例的實例化,所以推薦使用

2.枚舉單例

public enum Singleton{
INSTANCE;
public void done(){

}
}

使用枚舉的原因是因為枚舉單例最大的優點是簡單編寫,而且默認枚舉單例的創建是線程安全的,在任何情況下他都是一個單例。


總結:
這里優先推薦使用枚舉類型,考慮到上述的單例模式除了枚舉類型以外,其余在一種特殊的情況下會進行重新創建對象,那就是反序列化~

使用單例模式的優缺點:

優點:
由於單例模式在內存中只存在一個單例,減少內存開支特別是一個對象需要平凡創建和銷毀的時候。

缺點:
單例模式一般沒有借口,拓展很困難。
單例對象如果持有context對象,很容易引起內存的泄露,此時需要注意傳遞給單例的context最好是applicationcontext


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com