1. 程式人生 > >單例模式-獨一無二的物件

單例模式-獨一無二的物件

單例模式定義

確保某一個類只有一個例項,而且自行例項化並向整個系統提供這個例項,這個類稱為單例類,它提供全域性訪問的方法。

單例模式結構圖

在這裡插入圖片描述

單例模式角色介紹

單例模式只有一個角色,就是單例角色,Singleton,它自行例項化,並提供靜態方法獲取自行例項化的例項。

單例模式結構程式碼

單例類:

public class Singleton {
    //定義靜態變數
    private static Singleton singleton;

    //定義私有建構函式
    private Singleton(){
    }
    public static Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

客戶端:

public class Client {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        System.out.println("singleton = " + singleton);
    }
}

單例模式執行緒安全問題

上述結構圖和結構程式碼在多執行緒的環境下,無法保證建立的例項全域性唯一,這樣獲取單例物件的方式並不是一個執行緒安全的方式。可以通過兩種方式解決這個問題:餓漢式單例模式和懶漢式單例模式。

餓漢式單例模式

結構圖:
在這裡插入圖片描述
結構程式碼:

public class HungrySingleton {
    //定義靜態變數,類載入階段完成例項化
    private static HungrySingleton singleton = new HungrySingleton();
    //定義私有建構函式
    private HungrySingleton(){
    }
    public static HungrySingleton getInstance(){
        return singleton;
    }
}

優缺點:
優點是簡單,類載入階段就完成了例項化,不用考慮執行緒安全問題;缺點是啟動階段效率低,一般單例類例項化都伴隨著初始化資源的操作,類載入階段完成例項化和資源初始化,影響專案啟動效率,甚至導致專案無法啟動。

懶漢式單例模式

結構圖:
在這裡插入圖片描述
結構程式碼:

public class LazySingleton {
    //定義靜態變數,用volatile宣告
    private volatile static LazySingleton singleton;
    //定義私有建構函式
    private LazySingleton(){
    }
    public static LazySingleton getInstance(){
        synchronized (LazySingleton.class){
            if (singleton == null){
                singleton = new LazySingleton();
            }
        }
        return singleton;
    }
}

優缺點:
優點是既解決了執行緒安全問題,又解決了類載入階段初始化問題;缺點是多執行緒無法同時獲取單例例項,效率低。

優化的懶漢式單例模式

結構圖:
在這裡插入圖片描述
結構程式碼:

public class LazySingleton {
    //定義靜態變數,用volatile宣告
    private volatile static LazySingleton singleton;
    //定義私有建構函式
    private LazySingleton(){
    }
    public static LazySingleton getInstance(){
        //雙重判定,提高執行緒安全模式下效率
        if (singleton == null){
            synchronized (LazySingleton.class){
                if (singleton == null){
                    singleton = new LazySingleton();
                }
            }
        }
        return singleton;
    }
}

此方案既解決了執行緒安全問題,又解決了多執行緒無法同時獲取單例例項的問題,屬於單例模式的完美解決方案吧。

單例模式執行機制

單例類只有私有建構函式,定義一個私有靜態成員變數指向單例例項物件,然後提供靜態方法給客戶端,實現單例類物件的例項化。

單例模式解決的核心問題

單例模式,解決的是確保全域性只存在一個例項的問題,通過自行例項化和提供的靜態方法實現。