Android 常用單例模式簡單介紹

 /** 
  * 方式一 
  * instance 單例初始值是null,還未構(gòu)建,則構(gòu)建單例對象并返回;是懶漢模式    - 線程不安全 
  * instance 單例對象一開始就被new 出來,主動構(gòu)建,則不需要判空操作;是餓漢模式     - 線程安全 
  */  
 private ZpDanLiDemo(){}  
  
 private static ZpDanLiDemo instance = null;  
  
 public static ZpDanLiDemo getInstance() {  
     // (場景1:ZpDanLIDemo剛被初始化,線程1、2兩個線程同時調(diào)用 getInstance 方法,  
     // 所以instance為空,兩個線程同時通過條件判斷,對象創(chuàng)建了兩次)  
     if (instance == null) {  
         instance = new ZpDanLiDemo();  
     }  
     return instance;  
 } 

注:這種方式是線程不安全的,具體原因可以看注釋描述。
懶漢與餓漢兩種單例模式總是傻傻分不清,應用與面試的時候要多注意。

/** 
 * 方式二 
 */  
private ZpDanLiDemo(){}  
  
// volatile 對象new的時候,JVM執(zhí)行順序保證正常執(zhí)行  
private volatile static ZpDanLiDemo instance = null;  
  
public static ZpDanLiDemo getInstance() {  
    // 雙重檢測機制  
    if (instance == null) {  
        // 同步鎖 (為了對象不被 new 多次,使用同步鎖,鎖住整個類)  
        synchronized (ZpDanLiDemo.class) {  
            // 雙重檢測機制 (進入synchronized臨界區(qū)以后,還要再做一次判空。  
            // 因為當兩個線程同時訪問的時候,線程A構(gòu)建完對象,線程B也已經(jīng)通過  
            // 了最初的判空驗證,不做第二次判空的話,線程B還是會再次構(gòu)建instance對象)  
            if (instance == null) {  
                instance = new ZpDanLiDemo();  
            }  
        }  
    }  
    return instance;  
}  

注:這種方式是線程安全

/** 
 * 方式三 靜態(tài)內(nèi)部類實現(xiàn)單例模式 
 * 從外部是無法訪問靜態(tài)內(nèi)部類lazyHolder,只有當調(diào)用getInstance方法的時候,才能得到單例對象。 
 * instance 對象初始化的時機并不是在單例類ZpDanLiDemo被加載的時候,而是在調(diào)用
 *   getInstance方法,使得靜態(tài)內(nèi)部類LazyHolder被加載的時候。 
 * 因此這種實現(xiàn)方式是利用classLoader的加載機制來實現(xiàn)懶加載,并保證構(gòu)建單例的線程安全。 
 */  
private ZpDanLiDemo(){}  
  
private static class LazyHolder {  
    private static final ZpDanLiDemo instance = new ZpDanLiDemo();  
}  
  
public static ZpDanLiDemo getInstance() {  
    return LazyHolder.instance;  
}  

注:線程安全
使用靜態(tài)內(nèi)部類構(gòu)建單例,事件比較靠譜的一件事兒。個人喜好,是比較喜歡用這種方式。

使用反射機制打破單例

/** 
 * 利用反射打破單例 
 * 使用枚舉可以防止反射構(gòu)建 
 */  
private void getDanLi() {  
    try {  
        // 獲得構(gòu)造器  
        Constructor con = ZpDanLiDemo.class.getDeclaredConstructor(ZpDanLiDemo.class);  
        // 設(shè)置為可訪問  
        con.setAccessible(true);  
        // 構(gòu)造兩個不同的對象  
        ZpDanLiDemo zpDanLiDemo1 = new ZpDanLiDemo();  
        ZpDanLiDemo zpDanLiDemo2 = new ZpDanLiDemo();  
        // 驗證是否是不同對象 (log - > false)  
        Log.e("zpan", "====" + zpDanLiDemo1.equals(zpDanLiDemo2));  
  
    } catch (NoSuchMethodException e) {  
        e.printStackTrace();  
    }  
} 
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 單例模式(SingletonPattern)一般被認為是最簡單、最易理解的設(shè)計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,536評論 4 34
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,040評論 25 709
  • 風兒吹打在你的身上 太陽照耀著你的眼睛 鳥兒在你頭頂飛過 我靜靜地看著你 像是水墨畫里走出來的清新女神 黑夜里你與...
    日日是好日147閱讀 201評論 0 1
  • 刻意放下是永遠是放不下的,留給時間去完成這個艱巨的任務(wù),或許有一天我遇見一個更好的自己了,或者有個比他更能吸引...
    monamour6閱讀 212評論 0 0
  • 很喜歡很喜歡一個人的時候,真的可以委屈自己什么都不要。
    小杰cc閱讀 163評論 0 1

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