單例模式 六種寫法

單例的使用:有些對象只需要一個,比如:線程池、緩存、對話框、處理偏好設(shè)置和注冊表的對象、日志對象,充當(dāng)打印機(jī)、顯卡等設(shè)備的驅(qū)動程序的對象。

使用場景:1、要求生產(chǎn)唯一序列號;2、WEB 中的計數(shù)器,不用每次刷新都在數(shù)據(jù)庫里加一次,用單例先緩存起來;3、創(chuàng)建的一個對象需要消耗的資源過多,比如 I/O 與數(shù)據(jù)庫的連接等。

注意:其他的寫法,都是基于以下六種寫法。

/**
 * 單例模式
 * 定義:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點(diǎn)。
 * 
 * @author TinyDolphin
 * 2017/10/22 22:35.
 */
public class Singleton {

    /*//①、(懶漢式)lazy loading & 線程不安全 ,只適用于單線程環(huán)境(不好的解法)
    private Singleton(){}
    private static Singleton instance;
    public static Singleton getInstance(){
        if(instance == null)
            instance = new Singleton();
        return instance;
    }//*/

    /*//②、(懶漢式)lazy loading & 線程安全,但效率很低。(不好的解法)
       // 優(yōu)點(diǎn):lazy loading,避免內(nèi)存浪費(fèi)。
       // 缺點(diǎn):必須加鎖 synchronized 才能保證單例,而大部分時候我們是用不到同步的,所以不建議使用。
     private Singleton(){}
     private static Singleton instance;
     public static synchronized Singleton getInstance(){
         if(instance==null)
             instance = new Singleton();
         return instance;
     }
     //*/

    /*//③、(餓漢式)no lazy loading,線程安全,但容易產(chǎn)生垃圾對象。(不好的解法)
      // 優(yōu)點(diǎn):沒有加鎖,獲取對象得到速度快,執(zhí)行效率提高
      // 缺點(diǎn):類加載時就初始化,浪費(fèi)內(nèi)存,且類加載較慢
     private Singleton(){}
     private static Singleton instance = new Singleton();
     public static Singleton getInstance(){
         return instance;
     }
    //*/

    /*//④、雙檢鎖/雙重校驗鎖(DCL,即 double-checked locking),lazy loading & 線程安全(可行的解法)
       // 優(yōu)點(diǎn):資源利用率高,第一次執(zhí)行g(shù)etInstance 時單例對象才被實例化,效率高
       // 缺點(diǎn):第一次加載時稍慢,在高并發(fā)環(huán)境下也有一定的缺陷(發(fā)生的概率很?。?     private Singleton(){}
     private volatile static Singleton instance;
     public static Singleton getInstance(){
         if(instance == null){
             synchronized (Singleton.class){
                 if(instance == null){
                     instance = new Singleton();
                 }
             }
         }
         return instance;
     }
    //*/

    /*//⑤、登記式/靜態(tài)內(nèi)部類 lazy loading & 線程安全 (推薦使用,包括面試)
       // 第一次類加載并不會初始化 Instance,只有第一次調(diào)用 getInstance 方法時,虛擬機(jī)加載 SingletonHolder 并初始化 Instance
    private Singleton(){}
    private static class SingletonHolder{
        private static final Singleton INSTANCE = new Singleton();
    }
    public static final Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
     //*/

}
//⑥、實現(xiàn)單例模式的最佳方法。更簡潔,自動支持序列化機(jī)制,絕對防止多次實例化。但是大部分應(yīng)用開發(fā)很少用枚舉,可讀性不高,(不建議用)。
public enum Singleton {
    INSTANCE;
    public void whateverMethod(){}
}

下面擴(kuò)展一種:單例統(tǒng)一管理類

//用 SingletonManager 將多種的單例類統(tǒng)一管理,在使用時根據(jù) key 獲取對象對應(yīng)類型的對象(嚴(yán)格意義上,不能稱為單例,而算是如何管理類對象)
public class SingletonManager {
    private static Map<String,Object> objectMap = new HashMap<String,Object>();
    private SingletonManager(){}
    public static void registerService(String key,Object instance){
        if(!objectMap.containsKey(key)){
            objectMap.put(key,instance);
        }
    }
    public static Object getService(String key){
        return objectMap.get(key);
    }
}

經(jīng)驗之談:
第 ① 種和第 ② 種懶漢式:不建議使用;
第 ③ 種餓漢式建議使用;
第 ⑤ 種登記方式:在明確實現(xiàn) lazy loading 效果下使用(強(qiáng)烈建議使用,面試加分項);
第 ⑥ 種枚舉方式:涉及到反序列化創(chuàng)建對象;
第 ④ 種雙檢鎖方式:其他特殊的需求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,545評論 4 34
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,234評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,662評論 19 139
  • 本文參加#感悟三下鄉(xiāng),青春筑夢行#活動,本人承諾,文章內(nèi)容為原創(chuàng),且未在其他平臺發(fā)表過。 新鄉(xiāng)學(xué)院外國語學(xué)院實踐團(tuán)...
  • “知道了那么多道理,卻依然過不好這一生”。我們常常說:很多道理我都懂啊,可是我就是做不到。 是啊知道...
    二歡_笑8閱讀 308評論 0 0

友情鏈接更多精彩內(nèi)容