設(shè)計模式 ~ 單例模式

  • 七種常見的單例模式
  • 1钻心、懶漢式

/**
 * 單例模式 ~ 懶漢式
 *
 * @author LTP  2021/11/9
 */
class Singleton_lazy {

    private static Singleton_lazy mInstance;

    private Singleton_lazy() {
    }

    public static Singleton_lazy getInstance() {
        if (mInstance == null) {
            mInstance = new Singleton_lazy();
        }
        return mInstance;
    }
}
  • 特點:獲取單例時判空即可凄硼,線程不安全

2、線程安全的懶漢式

/**
 * 單例模式 ~ 線程安全的懶漢式
 *
 * @author LTP  2021/11/9
 */
class Singleton_lazySync {

    private static Singleton_lazySync mInstance;

    private Singleton_lazySync() {
    }

    public static synchronized Singleton_lazySync getInstance() {
        if (mInstance == null) {
            mInstance = new Singleton_lazySync();
        }
        return mInstance;
    }
}
  • 特點:在獲取單例的方法上加synchronized關(guān)鍵字保證線程安全捷沸,但每次獲取都加鎖效率比較低

3摊沉、雙重校驗鎖DCL(double check lock)

/**
 * 單例模式 ~ 雙重校驗鎖DCL(Double check lock)
 * 是針對線程安全的懶漢式的優(yōu)化版本
 *
 * @author LTP 2021/11/5
 */
public class Singleton_DCL {

    /**
     * volatile關(guān)鍵字(可見性、防止指令重排痒给、不保證原子性)此處用到了防止指令重排的特性
     * 在一個線程分配了mInstance所指向的內(nèi)存地址说墨,但并未初始化時(發(fā)生指令重排),
     * 第二個線程在第一個判空的位置會判斷mInstance不為空從而直接返回當(dāng)前mInstance苍柏,但事實上mInstance并未初始化而造成錯誤
     * 具體參考:https://blog.csdn.net/llllllkkkkkooooo/article/details/115360630
     */
    private static volatile Singleton_DCL mInstance;

    private Singleton_DCL() {
    }

    public static Singleton_DCL getInstance() {
        // 第一個判空是減少synchronized加鎖尼斧,提高效率
        if (mInstance == null) {
            // 執(zhí)行位置1
            synchronized (Singleton_DCL.class) {
                // 第二次判空是防止有多個線程調(diào)用getInstance()時都執(zhí)行在第一次判空之后并阻塞在synchronized之前(執(zhí)行位置1)
                // 從而導(dǎo)致一個線程中初始化后下一個線程繼續(xù)初始化,從而破壞單例
                if (mInstance == null) {
                    mInstance = new Singleton_DCL();
                }
            }
        }
        return mInstance;
    }
}

4、餓漢式

/**
 * 單例模式 ~ 餓漢式
 *
 * @author LTP  2021/11/9
 */
class Singleton_hungry {

    private static final Singleton_hungry mInstance = new Singleton_hungry();

    private Singleton_hungry() {
        System.out.println("構(gòu)造器");
    }

    public static Singleton_hungry getInstance() {
        return mInstance;
    }

    // 執(zhí)行順序:構(gòu)造器-main
    public static void main(String[] args) {
        System.out.println("main");
        Singleton_hungry instance =Singleton_hungry.getInstance();
    }
}
  • 特點:直接在類加載時初始化單例對象熄捍,保證唯一性

5烛恤、靜態(tài)內(nèi)部類

/**
 * 單例模式 ~ 靜態(tài)內(nèi)部類
 * 相比較餓漢式的好處是:第一次加載Singleton_staticInnerClass并不會初始化mInstance(調(diào)用構(gòu)造器),
 * 只有在調(diào)用getInstance()時,才會加載SingletonHolder從而初始化mInstance,
 * 參考:https://blog.csdn.net/weixin_30530523/article/details/96640126
 *
 * @author LTP  2021/11/9
 */
class Singleton_staticInnerClass {

    private Singleton_staticInnerClass() {
        System.out.println("構(gòu)造器");
    }

    public static Singleton_staticInnerClass getInstance() {
        return SingletonHolder.mInstance;
    }

    private static class SingletonHolder {
        public static final Singleton_staticInnerClass mInstance = new Singleton_staticInnerClass();
    }

    // 執(zhí)行順序:main-構(gòu)造器
    public static void main(String[] args) {
        System.out.println("main");
        Singleton_staticInnerClass instance =Singleton_staticInnerClass.getInstance();
    }
}

6、枚舉

/**
 * 枚舉宾添,一般不用枚舉,可讀性差柜裸,而且使用枚舉會造成內(nèi)存加大(每個枚舉類都會申明成一個靜態(tài)變量)缕陕,Android不推薦
 *
 * @author LTP  2021/11/9
 */
class Singleton_enum {

    public static void main(String[] args) {
        SingleTon singleTon = SingleTon.INSTANCE;
    }

    enum SingleTon {
        INSTANCE
    }
}
  • 特點:簡單,可讀性差疙挺,而且Android不推薦使用枚舉(加大內(nèi)存占用)

7扛邑、容器類

package com.btpj.design_pattern.singleton;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 單例模式 ~ 容器
 * 多種單例類統(tǒng)一管理,在使用時根據(jù)key獲取對象對應(yīng)類型的對象铐然。
 * 這種方式使得我們可以管理多種類型的單例蔬崩,并且在使用時可以通過統(tǒng)一的接口進行獲取操作恶座,
 * 降低了用戶的使用成本,也對用戶隱藏了具體實現(xiàn)沥阳,降低了耦合度
 *
 * @author LTP 2021/11/5
 */
public class Singleton_map {

    /**
     * 使用Map容器類統(tǒng)一管理各單例實例
     */
    private static Map<String, Object> mObjMap = new ConcurrentHashMap<>();

    private Singleton_map() {
    }

    /**
     * 將實例保存至Map容器
     *
     * @param key      key
     * @param instance 實例
     */
    public static void addInstance(String key, Object instance) {
        if (!mObjMap.containsKey(key)) {
            mObjMap.put(key, instance);
        }
    }

    /**
     * 根據(jù)key獲取單例類
     *
     * @param key key
     * @return 獲取到的單例類
     */
    public static Object getInstance(String key) {
        return mObjMap.get(key);
    }
}
  • 特點:可統(tǒng)一管理多種單例類跨琳,降低了用戶的使用成本,也對用戶隱藏了具體實現(xiàn)桐罕,降低了耦合度
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脉让,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子功炮,更是在濱河造成了極大的恐慌溅潜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薪伏,死亡現(xiàn)場離奇詭異滚澜,居然都是意外死亡,警方通過查閱死者的電腦和手機嫁怀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門设捐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人眶掌,你說我怎么就攤上這事挡育。” “怎么了朴爬?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵即寒,是天一觀的道長。 經(jīng)常有香客問我召噩,道長母赵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任具滴,我火速辦了婚禮凹嘲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘构韵。我一直安慰自己周蹭,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布疲恢。 她就那樣靜靜地躺著凶朗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪显拳。 梳的紋絲不亂的頭發(fā)上棚愤,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼宛畦。 笑死瘸洛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的次和。 我是一名探鬼主播反肋,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼斯够!你這毒婦竟也來了囚玫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤读规,失蹤者是張志新(化名)和其女友劉穎抓督,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體束亏,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡铃在,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了碍遍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片定铜。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖怕敬,靈堂內(nèi)的尸體忽然破棺而出揣炕,到底是詐尸還是另有隱情,我是刑警寧澤东跪,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布畸陡,位于F島的核電站,受9級特大地震影響虽填,放射性物質(zhì)發(fā)生泄漏丁恭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一斋日、第九天 我趴在偏房一處隱蔽的房頂上張望牲览。 院中可真熱鬧,春花似錦恶守、人聲如沸第献。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庸毫。三九已至,卻和暖如春押框,著一層夾襖步出監(jiān)牢的瞬間岔绸,已是汗流浹背理逊。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工橡伞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盒揉,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓兑徘,卻偏偏與公主長得像刚盈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挂脑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容