寂然解讀設計模式 - 單例模式(下)

I walk very slowly, but I never walk backwards 

設計模式 - 單例模式(下)


? 寂然

大家好~片排,我是寂然凿蒜,本節(jié)課呢,我們接著來聊單例模式显设,本節(jié)課的重點是單例模式最后兩種寫法,靜態(tài)內部類和枚舉藏畅,接著帶大家閱讀JDK源碼中單例模式的應用敷硅,以及對單例模式的注意事項進行總結,那我們啟程吧

靜態(tài)內部類

通過靜態(tài)內部類愉阎,同樣可以實現(xiàn)單例模式绞蹦,首先大家要對靜態(tài)內部類有了解, 用static修飾的內部類榜旦,稱為靜態(tài)內部類幽七, 我們先編寫代碼,驗證其正確性溅呢,然后對靜態(tài)內部類的寫法進行分析澡屡,示例代碼如下:

// 單例模式 - 靜態(tài)內部類
class Singleton{

    private Singleton(){

    }

    private static class SingletonInstance {

        public static final Singleton INSTANCE = new Singleton();

    }

    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

public class InnerClassDemo {
    public static void main(String[] args) {

        Singleton instance = Singleton.getInstance();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance == instance1);
    }
}
寫法分析

靜態(tài)內部類的特點是,當Singleton類進行類加載的時候咐旧,靜態(tài)內部類是不會被加載的

當調用Singleton類的 getInstance() 方法驶鹉,用到了 SingletonInstance 的靜態(tài)變量的時候,會導致靜態(tài)內部類SingletonInstance 進行類加載铣墨,當然類加載的過程中室埋,線程是安全的,所以這種寫法不會出現(xiàn)線程安全問題


這種方式采用類加載的機制來保證初始化實例時只有一個線程伊约, 類的靜態(tài)屬性只會在第一次加載類的時候初始化姚淆,所以在這里,JVM 幫助我們保證了線程的安全性屡律,在類進行初始化時腌逢,別的線程是無法進入的 ,避免了線程不安全超埋,利用靜態(tài)內部類特點實現(xiàn)延遲加載搏讶,效率也較高,所以這種方式也是推薦使用的

枚舉方式

通過枚舉的方式霍殴,其實也可以實現(xiàn)單例模式窍蓝,這是單例模式的第八種寫法,示例代碼如下

//單例模式 - 枚舉方式
enum Singleton{

    INSTANCE; //屬性

    public void method(){
        System.out.println("實例方法的打印");
    }
}

public class EnumDemo {
    public static void main(String[] args) {

        Singleton instance = Singleton.INSTANCE;
        Singleton instance1 = Singleton.INSTANCE;
        System.out.println(instance == instance1);
        instance.method();
    }
}
寫法分析

這借助 JDK1.5 中添加的枚舉來實現(xiàn)單例模式繁成,不僅能避免多線程同步問題吓笙,而且還能防止反序列化重新創(chuàng)建新的對象,這種方式是 Effective Java 作者 Josh Bloch 提倡的方式巾腕,在實際開發(fā)中面睛,同樣推薦使用這種方式

JDK源碼分析

JDK 中絮蒿,java.lang.Runtime 就是經典的餓漢式單例模式,我們寫一段測試代碼叁鉴,然后進行源碼分析

public class Test {
    public static void main(String[] args) {

        //得到一些系統(tǒng)信息
        Runtime runtime = Runtime.getRuntime();
        int processors = runtime.availableProcessors();
        long freeMemory = runtime.freeMemory();
        long maxMemory = runtime.maxMemory();

        System.out.println("freeMemory " + freeMemory); //空閑內存
        System.out.println("maxMemory " + maxMemory);   //最大內存
        System.out.println("processors " + processors);  //處理器個數(shù)
   
    }
}

通過源碼大家可以看到土涝,Runtime 就是經典的餓漢式寫法,首先Runtime類 java 中肯定會用到幌墓,不存在浪費但壮,其次,餓漢式的寫法常侣,類的加載過程中創(chuàng)建對象蜡饵,避免了線程安全問題

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /** Don't let anyone else instantiate this class */
    private Runtime() {}

注意事項

1,單例模式保證了系統(tǒng)內存中該類只存在一個對象胳施,節(jié)省了系統(tǒng)資源溯祸,對于一些需要頻繁創(chuàng)建銷毀的對象, 使用單例模式可以提高系統(tǒng)性能

2舞肆,當想實例化一個單例類的時候焦辅,必須要記住使用相應的獲取對象的方法,而不是使用 new

單例模式使用場景
  • 需要頻繁的進行創(chuàng)建和銷毀的對象
  • 創(chuàng)建對象時耗時過多或耗費資源過多(即:重量級對象)
  • 經常用到的對象
  • 工具類對象
  • 頻繁訪問數(shù)據庫或文件的對象(比如數(shù)據源椿胯、session 工廠等)

下節(jié)預告

OK筷登,到這里,單例模式就正式完結了哩盲,我們從單例模式的八種寫法入手前方,對每一種進行利弊分析,著重講解了雙重檢查機制种冬,最后镣丑,我們看了JDK源碼中單例模式的使用舔糖,以及給大家強調了單例模式的注意事項娱两,涉及的內容相對比較完整全面,下一節(jié)金吗,我們進入第二個設計模式 - 工廠模式的學習十兢,最后,希望大家在學習的過程中摇庙,能夠感覺到設計模式的有趣之處旱物,高效而愉快的學習,那我們下期見~

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末卫袒,一起剝皮案震驚了整個濱河市宵呛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夕凝,老刑警劉巖宝穗,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件户秤,死亡現(xiàn)場離奇詭異,居然都是意外死亡逮矛,警方通過查閱死者的電腦和手機鸡号,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來须鼎,“玉大人鲸伴,你說我怎么就攤上這事〗兀” “怎么了汞窗?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長糖荒。 經常有香客問我杉辙,道長,這世上最難降的妖魔是什么捶朵? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任蜘矢,我火速辦了婚禮,結果婚禮上综看,老公的妹妹穿的比我還像新娘品腹。我一直安慰自己,他們只是感情好红碑,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布舞吭。 她就那樣靜靜地躺著,像睡著了一般析珊。 火紅的嫁衣襯著肌膚如雪羡鸥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天忠寻,我揣著相機與錄音惧浴,去河邊找鬼。 笑死奕剃,一個胖子當著我的面吹牛衷旅,可吹牛的內容都是我干的。 我是一名探鬼主播纵朋,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼柿顶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了操软?” 一聲冷哼從身側響起嘁锯,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后家乘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體品山,經...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年烤低,在試婚紗的時候發(fā)現(xiàn)自己被綠了肘交。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扑馁,死狀恐怖涯呻,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情腻要,我是刑警寧澤复罐,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站雄家,受9級特大地震影響效诅,放射性物質發(fā)生泄漏。R本人自食惡果不足惜趟济,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一乱投、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧顷编,春花似錦戚炫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至钮惠,卻和暖如春茅糜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背素挽。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工蔑赘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毁菱。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓米死,卻偏偏與公主長得像锌历,于是被迫代替她去往敵國和親贮庞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353