單例模式全彙總——《Android源碼設計模式解析與實戰》讀書筆記

導語:單例模式應該是使用最爲廣泛的一種模式了,以前也知道懶漢式和惡漢式,但是沒有總結過,這次看到了關於單例模式的基本可能的實現方式,現在記錄一下,方便以後自己可以看。

一.餓漢式

/**
 * 餓漢式單例
 * Created by 追風車的面癱
 */
public class Singleton {
    public static final Singleton sInstance = new Singleton();
    public Singleton(){}
    public static Singleton getInstance(){
    return sInstance;
    }
}

特點:節省時間,但類創建之後就實例化了,無論使用與否,始終在內存中,線程始終是安全的。

二.懶漢式

   /**
   * 懶漢式單例
     * Created by 追風車的面癱
 */
public class Singleton {
    private static  Singleton sInstance = null;
    public Singleton(){
    }
    public synchronized static Singleton getsInstance(){
           if(sInstance==null){
            sInstance  = new Singleton();
        }
    return sInstance;
    }
}

特點:節省了空間,在需要的時候才創建,但第一次獲取時會有點慢,線程不安全。

三.雙重檢查鎖定

/**
   *
   * 雙重檢查鎖定單例
   * Created by 追風車的面癱
   */
public class Singleton {
    public Singleton(){
    }
    public static Singleton getsInstance(){
        if(sInstance == null){
            synchronized (Singleton.class){
                if(sInstance == null){
                    sInstance = new Singleton();
                }
            }
        }
    return sInstance;
        }
}

特點:既能在需要時初始化,又能夠保證線程安全,且單例對象初始化後調用getInstance()不進行同步鎖。
但是考慮到Java併發過程中,Java編譯器允許處理器亂序執行,有可能會有bug,造成空指針的錯誤,但JDK1.5開始,官方具體化了volatile關鍵字,可以解決這個問題,只需改一句代碼:

//volatile修飾後,更安全
private volatile static Singleton sInstance =null;

關於volatile關鍵字,可查看http://www.cnblogs.com/dolphin0520/p/3920373.html,講的非常清楚。

四.靜態內部類

/**
 * 靜態內部類實現單例    推薦
 * Created by 追風車的面癱
 */
public class Singleton {
    public Singleton(){
    }
        public static Singleton getInstance(){
        return SingletonHolder.sInstance;
    }
    /**
     * 靜態內部類
     */
    private static class SingletonHolder{
        private static final Singleton sInstance = new Singleton();
    }
}

特點:線程安全,也保證了對象唯一性。

五.枚舉單例

   /**
   *枚舉單例
*Created by 追風車的面癱
*/
public enum  Singleton {
    INSTANCE;
    public  void doSomething(){
        System.out.println("do sth.");
    }
}

特點:寫法簡單,默認線程就是安全的。相比以上幾個方式,有一個優點,即使反序列化也不會重新生成新的實例。

六.使用容器實現單例模式

   /**
 * Created by 追風車的面癱
 */
public class SingletonManager {
    private static Map<String,Object> objMap = new HashMap<String,Object>();
    private SingletonManager(){}
    public static void registerService(String key,Object instance){
        if(!objMap.containsKey(key)){
            objMap.put(key,instance);
        }
    }
    public static Object getService(String key){
        return objMap.get(key);
    }
}

特點:程序初始時,將多種單例類型注入到一個統一的管理類,使用時根據key獲取,可以管理多種單例。比如android源碼中Context的實現類ContextImpl類中就有用到這種方式的單例獲取相關Service。

總結:大部分情況下,推薦使用帶有volatile關鍵字的雙重檢查鎖定和靜態內部類。(希望以後能繼續堅持寫筆記和關於安卓的總結)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章