目錄android
單例模式數據庫
爲何使用單例模式設計模式
單例模式實際應用緩存
這個設計模式應該算是我最先接觸到一個,也是從那個時候知道有一種東西叫設計模式,看到這種代碼結構,有種將好的東西經過某種精美的包裝進行包裝同樣,似錦上添花。網絡
單例模式:單例模式中有一個單例類的結構,來保證系統中,該類只可以被實例化一個,經過這種方式控制系統中實例的個數,同時易於外界訪問。多線程
對於緩存,數據庫鏈接,網絡請求隊列等,資源消耗比較大的,一般咱們只是須要一個實例,來減小資源的消耗。
爲何不實用靜態全局變量來進行控制呢?
經過靜態全局變量持有一個咱們建立的實例,而後對這個實例進行一些操做不也是能夠保證單例嗎?這種方式彷佛要比多出一個設計模式去改變類的結構方便的多,可是咱們卻不會這樣去作,緣由就是線程
當咱們設置一個全局的變量在系統中,其會致使出現命名空間污染現象,致使咱們在一些引用的過程當中,出現了將全局變量做爲局部變量使用的狀況,設計
同時若是咱們對於靜態全局變量若是不加鎖的話,很容易在多線程操做的過程當中帶來同步上的一些問題,code
最後一個緣由就是若是咱們將其做爲一個靜態全局變量使用,那麼咱們就沒法實現一個惰性建立實例,對於過於消耗資源的實例,經過惰性建立,咱們將其拖延至使用時建立,而不會過早的消耗資源。對象
到了看一下單例模式廬山真面目的時候了,首先經過一段簡單的Java代碼看一下其大致結構。
public class Singleton{ private static Singleton mSingleton = null; private Singleton(){ } public static Singleton getInstance(){ if(mSingleton==null) mSingleton = new Singleton(); return mSingleton; } }
上面是一個簡單單例模式的示範代碼,經過這個代碼,咱們能夠看出單例類的構造方法是私有方法,也就是該類咱們沒有辦法經過new獲得的,只可以經過靜態的getInstance()方法獲得。可是對於多線程問題,若是有多個線程在執行這個方法,那麼可能就會有多個實例被建立出來,如何應對這個問題呢?
1.對該代碼區域進行同步
public class Singleton{ private static Singleton mSingleton = null; private Singleton(){ } public synchronized Singleton static getInstance(){ if(mSingleton==null) mSingleton = new Singleton(); return mSingleton; } }
當咱們對代碼塊進行加鎖以後,一個線程就要等到另外一個線程結束以後,才能夠繼續執行該區域代碼,可是當咱們對一個代碼區域進行加鎖以後,咱們的代碼效率就會下降100倍。對這個代碼區域進行同步以後,每當咱們執行這塊代碼,都將會出現一個等待。
2.急切建立實例,而不是採用惰性建立
public class Singleton{ private static Singleton mSingleton = new Singleton(); private Singleton(){ } public synchronized Singleton static getInstance(){ return mSingleton; } }
經過急切建立在對類進行初始化的時候就實例化了類,就不會出現多個線程競爭的問題,可是會致使的問題是若是建立實例消耗過大的時候就會出現提早消耗資源的問題。所以咱們常採用的一種方法是雙重加鎖法。
3.雙重檢查加鎖
public class Singleton{ private static Singleton mSingleton = null; private Singleton(){ } public Singleton static getInstance(){ if(mSingleton==null){ synchronized (Singleton.class){ if(mSingleton==null) mSingleton = new Singleton(); } } return mSingleton; } }
這種方式對於加鎖不是對整個方法進行加鎖,而是判斷當這個單例未被初始化以後,纔對這個實例的初始化區域進行一個同步,在同步的過程當中在進行一個是否實例化的判斷。即所謂的雙重檢查。課有疑問的在於,咱們已經進入了同步區域了,爲何還要對其作一個判斷呢?就是當兩個線程同時越過了第一個判斷以後,若是咱們在同步方法中沒有對與實例的判斷,這個時候,咱們就有可能出現實例被建立兩次的狀況。
綜上所述:綜合效率,資源消耗等來看,經過雙重檢查加鎖的方式來建立最爲方便。
單例模式在android中有那些應用呢?
android中有不少系統級別的全局變量,如時間,輸入法,帳戶,狀態欄等等
InputMethodManager類,CalendarDatabaseHelper類、Editable類等等。在這些類中,都存在一個方法getInstance,在該方法或直接返回對象的引用或判斷一個類的引用是否爲NULL,若不爲NULL,則直接返回該引用,若爲NULL,則new一個新的對象,並返回。例如,對於CalendarDatabaseHelper類,存在以下的代碼:
public static synchronized CalendarDatabaseHelper getInstance(Contextcontext) { if (sSingleton == null) { sSingleton = newCalendarDatabaseHelper(context); } return sSingleton; }
下一篇文章將更新關於裝飾器設計模式相關的