1. 程式人生 > 實用技巧 >大話設計模式讀書筆記(單例模式)

大話設計模式讀書筆記(單例模式)

人物:大鳥,小菜

事件:小菜在點選一個小工具的圖示時,每次點選都會建立一個窗體,但是小菜希望的是,第一次點選新建一個窗體,但是後面的每次點選都只會彈出以前建立的那個窗體,小菜很鬱悶,於是大鳥讓小菜藉此學習單例模式。


單例模式:

1.簡介單例模式,並講述了單例模式的懶漢式

2.介紹了單例模式的餓漢式

單例模式(懶漢式)

1.概念:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。

2.特點:單例模式只能有一個例項;單例類必須建立自己的唯一例項;單例類可以為其他類提供這一例項

3.懶漢式基礎程式碼實現:

Singleton類,即單例類:

public class Singleton {
    
private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }

客戶端:

@Slf4j
public class SingletonClient {
    public static void main(String[] args) {
        Singleton s1 
= Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); if (s1 == s2) { log.info("兩個物件是相同的例項"); } } }

輸出結果:

兩個物件是相同的例項

4.多執行緒下怎麼保證單例模式執行緒安全,即加鎖

注意:在多執行緒中,可能多個執行緒同時訪問Singleton類,為了避免建立多個例項,加鎖如下:

public class Singleton {
    private static Singleton instance;
    
private static final Object lock = new Object(); private Singleton() { } public static Singleton getInstance() { synchronized (lock) { if (instance == null) { instance = new Singleton(); } } return instance; } }

小菜:那這樣不是會每次都加鎖麼,可能沒有建立例項也直接加鎖了?

大鳥:那還可以做如下改動,先判斷例項是否為空,再看鎖不鎖

5.實現雙重鎖定如下:

public class Singleton {
    private static Singleton instance;
    private static final Object lock = new Object();

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

6.靜態內部類,保證執行緒安全由提高點效能:

public class Singleton {

    private Singleton() {
    }

    private static class LazyHolder {
        private static final Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return LazyHolder.instance;
    }
}

問:為什麼靜態內部類是執行緒安全的?

答:利用了類中靜態變數的唯一性,而且不加鎖效能會好很多

單例模式(餓漢式)

public class Singleton {

    private Singleton() {
    }

    private static final Singleton single = new Singleton();

    public static Singleton getInstance() {
        return single;
    }
}

問:為什麼這種方式是執行緒安全的?

答:在類建立的時候,也會建立類裡面的靜態物件,而靜態物件一旦建立,又利用了靜態變數的唯一性,和懶漢式的靜態內部類有些相似

問:那靜態內部類和餓漢式有什麼區別呢?

答:靜態內部類,需要時才載入類中的方法,又因為餓漢式裡一開始就將靜態變數載入,所以使用上的效能可能沒有餓漢式的好

餓漢式,第一次載入類時直接就將靜態變數載入了,但是如果後面一直不使用,就會造成記憶體的浪費