【設計模式】單例模式 餓漢式單例與懶漢式單例

單例模式(Singleton Pattern)詳解


一、單例模式簡介

單例模式(Singleton Pattern) 是一種 創建型設計模式,它確保一個類只有一個實例,并提供一個全局訪問點來獲取這個實例。(對象創建型模式)

簡單來說,就是:

“在整個應用程序中,某個類只能有一個對象存在。”

這在需要共享資源、統一管理狀態或控制訪問時非常有用。

在這里插入圖片描述
要點
某個類只能有一個實例
必須自行創建這個實例
必須自行向整個系統提供這個實例

單例模式只包含一個單例角色
Singleton(單例)

在這里插入圖片描述


私有構造函數
靜態私有成員變量(自身類型)
靜態公有的工廠方法

二、解決的問題類型

單例模式主要用于解決以下問題:

  • 多個對象造成資源浪費:比如數據庫連接池、線程池等,如果每次使用都新建對象,會造成性能浪費。
  • 需要全局唯一訪問入口:如配置管理器、日志記錄器等,希望整個系統中都通過同一個接口訪問。
  • 避免重復初始化帶來的錯誤:例如緩存服務、任務調度器等,不允許多個實例同時運行。

三、使用場景

場景示例
配置中心ConfigManager 管理應用的配置信息
日志記錄器Logger 實現統一的日志輸出
數據庫連接池DataSource 提供連接復用
緩存服務CacheManager 統一管理緩存數據
線程池管理ExecutorService 控制并發資源

四、實際生活案例

想象你在家里只有一臺電視遙控器。無論你是爸爸、媽媽還是孩子,大家都必須通過這一個遙控器來操作電視。如果你允許每個家庭成員都擁有自己的遙控器,那么可能會出現混亂操作和資源浪費。

在這個例子中,“遙控器”就是一個“單例”,全家人共享一個實例。


五、代碼案例(Java)

1. 懶漢式(線程不安全)

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

在這里插入圖片描述

?? 注意:這種方式在多線程環境下可能創建多個實例。


2. 懶漢式 + 同步方法(線程安全)

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

? 優點:線程安全
? 缺點:效率低,每次調用 getInstance() 都會加鎖


多個線程同時訪問將導致創建多個單例對象!怎么辦?👇👇👇

3. 雙重檢查鎖定(Double-Checked Locking)

class SingletonDCL {private static volatile SingletonDCL instance;private SingletonDCL() {}public static SingletonDCL getInstance() {if (instance == null) {synchronized (SingletonDCL.class) {if (instance == null) {instance = new SingletonDCL();}}}return instance;}
}

? 優點:線程安全、性能較好
? 推薦方式之一


4. 餓漢式(靜態常量)

class SingletonEager {private static final SingletonEager INSTANCE = new SingletonEager();private SingletonEager() {}public static SingletonEager getInstance() {return INSTANCE;}
}

在這里插入圖片描述

? 優點:實現簡單、線程安全
? 缺點:類加載時就初始化,可能造成資源浪費


5. 靜態內部類(推薦寫法)

class SingletonInnerClass {private SingletonInnerClass() {}private static class SingletonHolder {private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();}public static SingletonInnerClass getInstance() {return SingletonHolder.INSTANCE;}
}

? 優點:懶加載、線程安全、簡潔高效
? 最推薦寫法之一


餓漢式單例類與懶漢式單例類比較

餓漢式單例類:無須考慮多個線程同時訪問的問題;調用速度和反應時間優于懶漢式單例;資源利用效率不及懶漢式單例;系統加載時間可能會比較長
懶漢式單例類:實現了延遲加載;必須處理好多個線程同時訪問的問題;需通過雙重檢查鎖定等機制進行控制,將導致系統性能受到一定影響

6. 枚舉(最佳實踐)

enum SingletonEnum {INSTANCE;public void doSomething() {System.out.println("Doing something...");}
}

? 優點

  • 天然線程安全
  • 天然防止反射攻擊
  • 天然支持序列化/反序列化不破壞單例

? Joshua Bloch 推薦寫法(《Effective Java》作者)


其他案例:

  1. 某軟件公司承接了一個服務器負載均衡(Load Balance)軟件的開發工作,該軟件運行在一臺負載均衡服務器上,可以將并發訪問和數據流量分發到服務器集群中的多臺設備上進行并發處理,提高了系統的整體處理能力,縮短了響應時間。由于集群中的服務器需要動態刪減,且客戶端請求需要統一分發,因此需要確保負載均衡器的唯一性,只能有一個負載均衡器來負責服務器的管理和請求的分發,否則將會帶來服務器狀態的不一致以及請求分配沖突等問題。如何確保負載均衡器的唯一性是該軟件成功的關鍵,試使用單例模式設計服務器負載均衡器。
    在這里插入圖片描述

  2. 身份證號碼:在現實生活中,居民身份證號碼具有唯一性,同一個人不允許有多個身份證號碼,第一次申請身份證時將給居民分配一個身份證號碼,如果之后因為遺失等原因補辦時,還是使用原來的身份證號碼,不會產生新的號碼。現使用單例模式模擬該場景。
    在這里插入圖片描述

  3. 打印池:在操作系統中,打印池(Print Spooler)是一個用于管理打印任務的應用程序,通過打印池用戶可以刪除、中止或者改變打印任務的優先級,在一個系統中只允許運行一個打印池對象,如果重復創建打印池則拋出異常。現使用單例模式來模擬實現打印池的設計。
    在這里插入圖片描述

六、優缺點分析

優點描述
? 節省資源只創建一次實例,避免重復創建銷毀帶來的性能開銷
? 全局訪問提供統一的訪問入口,便于集中管理
? 控制狀態一致性避免多個實例導致的數據不一致問題
其他允許可變數目的實例(多例類)
缺點描述
? 違反單一職責原則單例類通常承擔了太多責任,不符合高內聚低耦合原則
? 不利于測試依賴全局狀態,難以進行單元測試
? 隱藏依賴關系使用單例時不容易看出類之間的依賴關系
? 擴展困難如果將來需要支持多個實例,重構成本較高
其他由于自動垃圾回收機制,可能會導致共享的單例對象的狀態丟失

七、最終小結

單例模式是 Java 開發中最常用的設計模式之一,它的核心思想是:

保證一個類只有一個實例,并提供全局訪問入口。

作為一名 Java 開發工程師,掌握單例模式是非常有必要的,尤其是在開發工具類、配置管理器、緩存服務等組件時。

? 推薦使用方式總結:

寫法是否推薦適用場景
枚舉???最佳選擇,防反射、線程安全
靜態內部類??常規項目首選
DCL?手動控制懶加載
餓漢式??類加載即初始化,適合簡單場景
懶漢式?多線程下不安全,慎用

📌 一句話總結:

單例模式就像你家里的“總開關”,不管誰去按,都是控制同一個燈,確保系統的“唯一性”和“一致性”。

如果你正在構建一個需要全局統一管理的組件,不妨考慮使用單例模式。

部分內容由AI大模型生成,注意識別!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914135.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914135.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914135.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue3 el-table 行數據沾滿格自動換行

在使用 Vue 3 結合 Element Plus 的 <el-table> 組件時&#xff0c;如果你希望當表格中的行數據文本過長時能夠自動換行&#xff0c;而不是溢出到其他單元格或簡單地截斷&#xff0c;你可以通過以下幾種方式來實現&#xff1a;方法 1&#xff1a;使用 CSS最簡單的方法是通…

windows電腦遠程win系統服務器上的wsl2

情況 我自己使用win11筆記本電腦&#xff0c;想要遠程win11服務器上的wsl2 我這里只有服務器安裝了wsl2&#xff0c;win11筆記本沒有安裝 因此下面提到的Ubuntu終端指的是win服務器上的wsl2終端 一定要區分是在哪里輸入命令&#xff01;&#xff01; 安裝SSH 在服務器上&#x…

神經輻射場 (NeRF):重構三維世界的AI新視角

神經輻射場 (NeRF)&#xff1a;重構三維世界的AI新視角 舊金山蜿蜒起伏的街道上&#xff0c;一輛裝備12個攝像頭的Waymo自動駕駛測試車緩緩駛過。它記錄的280萬張街景圖像并未被簡單地拼接成平面地圖&#xff0c;而是被輸入一個名為Block-NeRF的神經網絡。數周后&#xff0c;一…

Kubernetes自動擴縮容方案對比與實踐指南

Kubernetes自動擴縮容方案對比與實踐指南 隨著微服務架構和容器化的廣泛采用&#xff0c;Kubernetes 自動擴縮容&#xff08;Autoscaling&#xff09;成為保障生產環境性能穩定與資源高效利用的關鍵技術。面對水平 Pod 擴縮容、垂直資源調整、集群節點擴縮容以及事件驅動擴縮容…

【CVPR2025】計算機視覺|SIREN: 元學習賦能!突破INR高分辨率圖像分類難題

論文地址&#xff1a;https://arxiv.org/pdf/2503.18123v1 代碼地址&#xff1a;https://github.com/SanderGielisse/MWT 關注UP CV縫合怪&#xff0c;分享最計算機視覺新即插即用模塊&#xff0c;并提供配套的論文資料與代碼。 https://space.bilibili.com/473764881 摘要 …

牛客周賽 Round 99

賽時成績如下&#xff1a;A. Round 99題目描述 對于給定的五位整數&#xff0c;檢查其中是否含有數字 99&#xff1b;換句話說&#xff0c;檢查是否存在相鄰的兩個數位&#xff0c;其值均為 。解題思路&#xff1a; 檢查相鄰的兩個數字是否均為9#include <bits/stdc.h> u…

從0到1搭建個人技術博客:用GitHub Pages+Hexo實現

一、為什么要搭建個人技術博客&#xff1f; 在技術圈&#xff0c;擁有個人博客的好處不言而喻&#xff1a; 簡歷加分項&#xff1a;面試官更青睞有技術沉淀的候選人知識系統化&#xff1a;輸出倒逼輸入&#xff0c;加深技術理解人脈拓展&#xff1a;吸引同行關注&#xff0c;…

Ubuntu22.04 設置顯示存在雙屏卻無法雙屏顯示

文章目錄一、背景描述二、解決方法一、背景描述 回到工位后&#xff0c;發現昨天離開時還可正常顯示的雙屏&#xff0c;今早ubuntu22.04 的設置界面顯示有雙屏&#xff0c;但外接的顯示屏無法正常顯示。 首先&#xff0c;查看當前圖像處理顯卡是否為N卡&#xff0c;沒錯&#…

高亞科技簽約奕源金屬,助力打造高效智能化采購管理體系

深圳市奕源金屬制品有限公司近日&#xff0c;國內企業管理軟件服務商高亞科技與深圳市奕源金屬制品有限公司&#xff08;以下簡稱“奕源金屬”&#xff09;正式簽約&#xff0c;雙方將基于高亞科技自主研發的8Manage SRM采購管理系統&#xff0c;共同推動奕源金屬采購管理的數字…

數據結構之map

map的基本介紹我們常常把map稱之為映射&#xff0c;就是將一個元素&#xff08;通常稱之為key鍵&#xff09;與一個相對應的值&#xff08;通常稱之為value&#xff09;關聯起來&#xff0c;比如說一個學生的名字&#xff08;key&#xff09;有與之對應的成績&#xff08;value…

vue3 canvas 選擇器 Canvas 增加頁面性能

文章目錄Vue3 選擇器 Canvas 增加頁面性能基于Vue3 Composition API和Canvas實現的交互式選擇器&#xff0c;支持PC端和移動端的拖動選擇、多選取消選擇功能vue3組件封裝html代碼Vue3 選擇器 Canvas 增加頁面性能 基于Vue3 Composition API和Canvas實現的交互式選擇器&#xf…

Python 實戰:打造多文件批量重命名工具

引言在實際運維、測試、數據分析、開發流程中&#xff0c;我們經常會處理成百上千條命令操作&#xff0c;例如&#xff1a;各種腳本任務&#xff08;啟動、備份、重啟、日志查看&#xff09;數據處理流程&#xff08;爬取 → 清洗 → 統計 → 可視化&#xff09;配置自動化&…

設計模式筆記_結構型_代理模式

1. 代理模式介紹代理模式是一種結構型設計模式&#xff0c;它允許你提供一個代理對象來控制對另一個對象的訪問。代理對象通常在客戶端和目標對象之間起到中介作用&#xff0c;能夠在不改變目標對象的前提下增加額外的功能操作&#xff0c;比如延遲初始化、訪問控制、日志記錄等…

C語言<數據結構-單鏈表>(收尾)

上篇博客我將基礎的尾插、尾刪、頭插、頭刪逐一講解了&#xff0c;這篇博客將對上篇博客進行收尾&#xff0c;講一下指定位置操作增刪以及查找這幾個函數&#xff0c;其實大同小異&#xff1a;一.查找函數&#xff1a;查找函數其實就是一個簡單的循環遍歷&#xff0c;所以不加以…

十年架構心路:從單機到云原生的分布式系統演進史

十年架構心路&#xff1a;從單機到云原生的分布式系統演進史 這里寫目錄標題十年架構心路&#xff1a;從單機到云原生的分布式系統演進史一、技術生涯的起點&#xff1a;單體架構的黃金時代1.1 典型技術棧1.2 記憶深刻的故障二、分布式架構轉型期2.1 服務化拆分實踐2.2 分布式事…

使用docker搭建nginx

安裝docker 和 docker compose驗證docker版本配置docker目錄配置代理&#xff0c;使docker能訪問外網能否ping通最后直接拉入鏡像即可docker pull nginx

Intel新CPU助攻:微軟Copilot+將登陸臺式電腦

微軟的Copilot PC計劃已經推出一年多&#xff0c;但目前僅支持平板電腦和筆記本電腦&#xff0c;以及少數迷你電腦。 隨著Intel下一代桌面處理器——代號為“Arrow Lake Refresh”的推出&#xff0c;Copilot PC功能有望擴展到桌面計算機。 要支持Copilot PC的所有功能&#xff…

【Kubernetes】跨節點 Pod 網絡不通排查案例

最近在部署一個集群環境的時候&#xff0c;發現集群中一個子節點與其他子節點不通&#xff0c;而 master 節點可與任何子節點互通&#xff0c;通過抓包排查后&#xff0c;發現是 Linux 路由決策導致的。因此&#xff0c;在此記錄下來&#xff0c;希望對大家有所幫助。1、環境及…

【算法訓練營Day11】二叉樹part1

文章目錄理論基礎二叉樹的遞歸遍歷前序遍歷中序遍歷后序遍歷總結二叉樹的層序遍歷基礎層序遍歷二叉樹的右視圖理論基礎 二叉樹在結構上的兩個常用類型&#xff1a; 滿二叉樹完全二叉樹 在功能應用上的比較常用的有&#xff1a; 二叉搜索樹&#xff1a; 節點有權值、遵循”左…

Flutter 之 table_calendar 控件

1.庫導入在pubspec.yaml文件中dev_dependencies:table_calendar: ^3.2.02. 代碼編寫TableCalendar(daysOfWeekHeight: 20,availableGestures: AvailableGestures.horizontalSwipe,firstDay: DateTime.now().subtract(const Duration(days: 365)),lastDay: DateTime.now(),cal…