1. 程式人生 > >android中單例模式的優缺點

android中單例模式的優缺點

    本篇文章主要介紹android開發中常用的單例模式和其中的幾種寫法,分析介紹在安卓開發中單例模式的優缺點。

一、常見的幾種單例模式

    首先來回顧一下幾種常見的單例模式,分析一下個自的優缺點

    1.懶漢式

    //懶漢式單例類.在第一次呼叫的時候例項化自己   
    public class TestSingleton {  
        private TestSingleton() {}  
        private static TestSingleton single=null;  
        //靜態工廠方法   
        public static TestSingleton getInstance() {  
         if (single == null) {    
             single = new TestSingleton();  
         }    
        return single;  
        }  

    } 

優點:

避免了餓漢式的那種在沒有用到的情況下建立事例,資源利用率高,不執行getInstance()就不會被例項,可以執行該類的其他靜態方法。

缺點:

懶漢式在單個執行緒中沒有問題,但多個執行緒同事訪問的時候就可能同時建立多個例項,而且這多個例項不是同一個物件,雖然後面建立的例項會覆蓋先建立的例項,但是還是會存在拿到不同物件的情況。

為了解決懶漢式造成的執行緒不安全以及可能會建立不同例項的問題,在此使用靜態內部類的方式對懶漢式單例進行升級

public class TestSingleton {    
    private static class LazyHolder {    
       private static final TestSingleton instance = new TestSingleton

();    
    }    
    private TestSingleton (){}    
    public static final TestSingleton getInstance() {    
       return LazyHolder.instance;    
    }    

這樣既實現了執行緒安全,又避免了同步帶來的效能影響。

優點 
    資源利用率高,不執行getInstance()不被例項,可以執行該類其他靜態方法 
缺點 
    第一次載入時反應不夠快

2.餓漢式

//餓漢式單例類.在類初始化時,已經自行例項化   
public class TestSingleton {  
    private TestSingleton() {}  
    private static final TestSingleton single = new TestSingleton

();  
    //靜態工廠方法   
    public static TestSingleton getInstance() {  
        return single;  
    }  


優點 
    1.執行緒安全 
    2.在類載入的同時已經建立好一個靜態物件,呼叫時反應速度快 
缺點 
    資源效率不高,可能getInstance()永遠不會執行到,但執行該類的其他靜態方法或者載入了該類(class.forName),那麼這個例項仍然初始化

二、android中專有的單例模式

    1.Activity中的單例

    在android中,由於Activity不可以建立物件,所以要想給Activity設定單例,可以在Activity初始化的時候在onCreate()中對Activity,宣告一個靜態的變數,在Activity初始化時傳遞上下文。

public static MainActivity instance = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    instance = this;

}

此單例跟隨Activity的生命週期,如果Activity死掉了 那麼此單例也會死掉

2.自定義View中的單例

當我們寫好了一個自定義View的類,一般情況下是需要把它載入到指定的Xml檔案中,當這個Xml檔案啟動的時候,對應的自定義View就會載入,這個時候如果通過普通的餓漢式或懶漢式生命單例就會出現錯誤,所以就需要在自定義View初始化時的構造方法中宣告單例,如下:

public static TestSingleView instance=null;
public TestSingleView (Context context) {
    super(context);
    this.context=context;
instance=this;
initView();
}

public TestSingleView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    this.context=context;
instance=this;
initView();
}

此單例的生命週期跟隨傳遞過來的上下文的生命週期。

三、單例模式的優缺點

1.優點

(1)由於單例模式在記憶體中只有一個例項,減少了記憶體開支,特別是一個物件需要頻繁地建立、銷燬時,而且建立或銷燬時效能又無法優化,單例模式的優勢就非常明顯。
(2)由於單例模式只生成一個例項,所以減少了系統的效能開銷,當一個物件的產生需要比較多的資源時,比如讀取配置、產生其他依賴物件時,則可以通過在應用啟動時直接產生一個單例物件,然後用永久駐留記憶體的方式來解決。
(3)單例模式可以避免對資源的多重佔用,例如一個寫檔案操作,由於只有一個例項存在記憶體中,避免對同一個資原始檔的同時寫操作。

(4)單例模式可以在系統設定全域性的訪問點,優化和共享資源訪問,例如,可以設計一個單例類,負責所有資料表的對映處理。

2.缺點

(1)單例模式一般沒有介面,擴充套件很困難,若要擴充套件,除了修改程式碼基本上沒有第二種途徑可以實現。

(2)單例物件如果持有Context,那麼很容易引發記憶體洩露,此時需要注意傳給單例物件的Context最好是Application Context。

(3)濫用單例將帶來一些負面問題,如為了節省資源將資料庫連線池物件設計為的單例類,可能會導致共享連線池物件的程式過多而出現連線池溢位;如果例項化的物件長時間不被利用,系統會認為是垃圾而被回收,這將導致物件狀態的丟失。