引言
這是設計模式專欄的第一篇文章,在這個專欄里面會講到我們在開發中經常使用的設計模式,我會用心將它們解析,然后講給你們聽,如果感興趣可以持續關注這個專欄??
這次我們要講的是單例模式,這個在大廠面試中十分常見,有的面試官會讓你手撕一個單例模式。拋去面試不談,單例模式也是我們開發中常用的軟件設計思想,許多框架的底層設計都是運用到這個設計思路,所以掌握好單例模式十分有必要
什么是單例模式🤓
單例模式(Singleton Pattern)是一種創建型設計模式,它確保一個類只有一個實例,并提供一個全局訪問點來訪問這個實例。
使用單例模式的場景有哪些呢?
- 數據庫連接池
- 日志記錄器(Logger)
- 配置管理器
- 線程池
- 緩存服務
這些對象只需要一個實例,避免重復創建造成資源浪費或狀態不一致。
單例模式的特點🥱
- 私有構造函數:防止外部通過?
new
?創建實例。 - 靜態私有實例:類內部維護唯一的實例。
- 公開的靜態方法:用于返回唯一實例。
單例模式創建分為餓漢式和懶漢式,接下來讓我們一一解析
餓漢式😈
為什么叫餓漢式呢?因為類加載就會導致該單實例對象被創建。
那類加載又是什么呢?
在 Java 中,類加載 是指將 .class
文件(字節碼文件)加載到 JVM(Java 虛擬機)中,并為其創建一個 java.lang.Class
對象的過程。這個過程是由 類加載器(ClassLoader) 完成的。
但是JVM不會在一開始就加載所有的類,而是在運行時按需加載,也就是說當某個類第一次被主動使用時才會觸發類加載。例如:
- 創建類的實例(
new
) - 訪問類的靜態變量或調用靜態方法
- 使用子類時會先加載父類
- 啟動類(main 方法所在的類)
還有一些被動引用的情況不會觸發類加載,比如訪問靜態常量(編譯期確定的 final static 常量),就不會觸發類初始化。
下面講講餓漢式怎么創建單例:
方法一:靜態成員變量方式獲取對象
public class Singleton{//1. 私有無參構造方法private Singleton(){}//2. 創建對象private static Singleton instance = new Singleton();//3. 向外提供公共方法,可以獲取單例對象public static Singleton getInstance(){return instance;}
}
方法二:靜態代碼塊創建
public class Singleton{//1. 私有無參構造方法private Singleton(){}//2. 創建對象private static Singleton instance;//3. 靜態代碼塊進行賦值static{instance = new Singleton();}//4. 向外提供公共方法,可以獲取單例對象public static Singleton getInstance(){return instance;}
}
方法三:枚舉
枚舉類型是線程安全的,并且只會裝載一次。枚舉是單例實現中唯一一種不會被破壞的單例實現模式
public enum Singleton{INSTANCE;
}
懶漢式🥱
懶漢式,顧名思義就是,意思就是需要創建的時候再創建。類加載并不會導致該單實例對象創建,而是首次使用該對象時才會創建。
public class Singleton{//1. 私有無參構造方法private Singleton(){}//2. 創建對象,使用volatile關鍵字防止指令重排序與保證變量可見性private static volatile Singleton instance;//3. 向外提供公共方法,可以獲取單例對象public static Singleton getInstance() {if (instance == null) {//synchronized關鍵字修飾代碼塊保證只有一個線程可以創建單例對象synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
總結??
這就是單例模式的解析,我們下次再見。
如果你看了這篇文章有收獲可以點贊+關注+收藏🤩,這是對筆者更新的最大鼓勵!如果你有更多方案或者文章中有錯漏之處,請在評論區提出幫助筆者勘誤,祝你拿到更好的offer!