設計模式 創建型 單例模式(Singleton Pattern)與 常見技術框架應用 解析

在這里插入圖片描述

單例模式(Singleton Pattern)是一種創建型設計模式,旨在確保某個類在應用程序的生命周期內只有一個實例,并提供一個全局訪問點來獲取該實例。這種設計模式在需要控制資源訪問、避免頻繁創建和銷毀對象的場景中尤為有用。

一、核心思想

單例模式的核心思想是限制類的實例化次數,確保整個應用程序中只有一個實例存在,并且這個實例可以被全局訪問。這通常通過私有化構造函數、提供一個靜態方法來獲取實例的方式實現。

  1. 唯一性:保證一個類在系統中只有一個實例。
  2. 控制訪問:提供一個全局訪問點來獲取該實例。
  3. 延遲初始化(可選):實例化可以延遲到第一次使用時,以節省資源。
實現單例模式的關鍵要素:
  • 私有構造函數:防止外部通過new關鍵字創建新的實例。
  • 靜態方法或屬性:用于存儲和返回唯一的實例。
  • 線程安全:如果應用是多線程的,則需要確保在并發環境下也能正確工作。

二、定義與結構

定義:單例模式確保一個類只有一個實例,并提供一個全局訪問點來獲取該實例。

結構

  • 單例類:負責創建和管理唯一的實例。
  • 靜態成員變量:用于保存唯一的實例引用。
  • 獲取實例方法:通常是一個靜態方法,用于返回唯一的實例。
  • 私有構造函數:防止外部通過構造函數創建多個實例。
角色
  • 單例類:包含私有構造函數、靜態成員變量和獲取實例的靜態方法。

三、實現步驟及代碼示例

以Java為例,單例模式的實現方式有多種,包括餓漢式、懶漢式、雙重檢查鎖定(Double-Checked Locking)和靜態內部類實現方式等。以下是幾種常見實現的代碼示例:

1、餓漢式

  • 特點:在類加載時就創建實例,沒有延遲加載的效果,但避免了多線程的同步問題。
  • 優點:線程安全,執行效率高。
  • 缺點:可能導致內存浪費,因為實例在類加載時就已創建,即使未使用。
public class HungrySingleton implements Serializable {private static final long serialVersionUID = 1L;private static final HungrySingleton hungry = new HungrySingleton();private HungrySingleton() {// 防止反序列化時重新創建實例if (hungry != null) {throw new RuntimeException("請使用 HungrySingleton.getInstance() 方法獲取一個單例實例");}}public static HungrySingleton getInstance() {return hungry;}// 其他方法...
}

2、懶漢式(線程不安全)

  • 特點:按需加載,節省資源,只有在確實需要的時候才會創建實例。但存在線程安全問題。

  • 優點:延遲加載,提高了程序啟動的速度。

  • 缺點:在多線程環境下需要額外的同步機制來保證線程安全。

  • 線程不安全的懶漢式示例代碼:

public class LazySingleton {private static LazySingleton lazyMan;public LazySingleton() {// 構造函數可以為空或包含初始化代碼}public static LazySingleton getInstance() {if (lazyMan == null) {lazyMan = new LazySingleton();}return lazyMan;}// 其他方法...
}

上述代碼在多線程環境下可能會出現多個實例,因此線程不安全。

注意:懶漢式(線程不安全)在多線程環境下可能會導致多個實例被創建,因此通常不推薦使用。

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

線程安全的懶漢式示例代碼(雙重檢查鎖定):

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

使用volatile關鍵字確保在多線程環境中正確處理,雙重檢查鎖定保證了線程安全和性能。

4、靜態內部類實現方式

  • 特點:利用Java的類加載機制實現延遲加載,線程安全且高效。

  • 優點:實現簡單,無需額外的同步機制。

  • 缺點:無法支持非靜態單例需求。

  • 示例代碼:

public class InnerClassSingleton {private InnerClassSingleton() {// 構造函數可以為空或包含初始化代碼}private static class Holder {private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();}public static InnerClassSingleton getInstance() {return Holder.INSTANCE;}// 其他方法...
}

5、枚舉單例

  • 特點:實現簡單,線程安全,防止反射和序列化破壞。

  • 優點:最簡潔的實現方式,由Java語言本身保證線程安全性。

  • 缺點:不支持延遲加載。

  • 示例代碼:

public enum Singleton {INSTANCE;public void someMethod() {// 單例方法邏輯}
}

四、JavaScript中的單例模式實現

基本實現

class Singleton {constructor() {if (typeof Singleton.instance === 'object') {return Singleton.instance;}Singleton.instance = this;}static getInstance() {if (!this.instance) {new this();}return this.instance;}someBusinessLogic() {// ...業務邏輯...}
}// 使用示例
const instanceA = Singleton.getInstance();
const instanceB = Singleton.getInstance();console.log(instanceA === instanceB); // true

模塊模式下的單例

在JavaScript中,模塊本身就是一個天然的單例,因為每個模塊只會被加載一次。因此,可以利用ES6模塊來實現單例模式。

// singleton.js
const singleton = (() => {let privateState = {}; // 私有狀態function somePrivateMethod() {// 私有方法}return {publicMethod: function() {// 公共方法somePrivateMethod();},getPrivateState: function() {return privateState;}};
})();export default singleton;// 在其他文件中導入并使用
import singleton from './singleton';singleton.publicMethod();
console.log(singleton.getPrivateState());

線程安全的單例(適用于Node.js)

當涉及到多線程環境時,如Node.js worker_threads,可能需要確保線程安全。

class ThreadSafeSingleton {constructor() {if (!ThreadSafeSingleton.instance) {ThreadSafeSingleton.instance = this;}return ThreadSafeSingleton.instance;}static getInstance() {if (!this.instance) {// 如果是在多線程環境中,這里應該加入鎖機制// 例如使用Promise或其他同步機制來保證線程安全new this();}return this.instance;}someBusinessLogic() {// ...業務邏輯...}
}

使用立即執行函數表達式(IIFE)

這是一種經典的JavaScript單例實現方式,尤其是在不支持模塊化的舊版本瀏覽器中。

const singleton = (function () {const privateState = {}; // 私有狀態function privateMethod() {// 私有方法}return {publicMethod: function () {// 公共方法privateMethod();},getPrivateState: function () {return privateState;}};
})();

五、常見技術框架應用

在Spring框架中,單例模式也得到了廣泛應用。Spring容器默認創建的Bean是單例的,即在整個Spring IoC容器中,一個Bean只會有一個實例。以下是Spring中配置單例Bean的示例:

<bean id="myBean" class="com.example.MyBean" singleton="true"/>

或者,在基于注解的配置中,可以通過@Component@Bean注解來定義Bean,并默認其為單例:

@Component
public class MyBean {// ...
}@Configuration
public class AppConfig {@Beanpublic MyBean myBean() {return new MyBean();}
}

六、應用場景

單例模式常用于以下場景:

  1. 日志記錄器:在整個應用程序中,通常只需要一個日志記錄器來記錄日志信息。
  2. 配置管理器:應用程序的配置信息通常只需要一個實例來管理,以確保配置的一致性。
  3. 數據庫連接池:為了有效地管理數據庫連接,避免頻繁地創建和銷毀連接,通常使用單例模式來創建數據庫連接池。
  4. 線程池:管理和復用線程,避免頻繁地創建和銷毀線程,提高系統性能。
  5. 全局計數器:在需要全局唯一的計數器時,可以使用單例模式。
  6. 購物車服務:在電子商務網站中,用戶的購物車應當是唯一的。
  7. 窗口管理器:圖形界面程序中,窗口管理器應確保只有一個實例來協調所有窗口的行為。

七、優缺點

優點

  1. 延遲加載:只有在需要時才創建實例,節省資源。
  2. 全局訪問點:提供一個全局訪問對象的方式,方便在不同模塊和組件之間共享資源。
  3. 控制資源:在需要限制實例數量的場景下(如數據庫連接池、日志系統),單例模式能夠確保系統中只有一個實例在操作資源。

缺點

  1. 線程安全問題:在多線程環境下,需要額外的同步機制來確保線程安全,可能會影響性能。
  2. 單例類的職責單一:單例模式通常要求單例類只承擔一個職責,否則可能會違背單一職責原則,導致代碼難以維護。

綜上所述,單例模式是一種非常有用的設計模式,在需要控制資源訪問和避免頻繁創建對象的場景中發揮著重要作用。然而,在使用時也需要注意其潛在的缺點,并根據具體場景選擇合適的實現方式。
在這里插入圖片描述

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

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

相關文章

您的公司需要小型語言模型

當專用模型超越通用模型時 “越大越好”——這個原則在人工智能領域根深蒂固。每個月都有更大的模型誕生&#xff0c;參數越來越多。各家公司甚至為此建設價值100億美元的AI數據中心。但這是唯一的方向嗎&#xff1f; 在NeurIPS 2024大會上&#xff0c;OpenAI聯合創始人伊利亞…

uniapp-vue3(下)

關聯鏈接&#xff1a;uniapp-vue3&#xff08;上&#xff09; 文章目錄 七、咸蝦米壁紙項目實戰7.1.咸蝦米壁紙項目概述7.2.項目初始化公共目錄和設計稿尺寸測量工具7.3.banner海報swiper輪播器7.4.使用swiper的縱向輪播做公告區域7.5.每日推薦滑動scroll-view布局7.6.組件具名…

使用 Python 實現隨機中點位移法生成逼真的裂隙面

使用 Python 實現隨機中點位移法生成逼真的裂隙面 一、隨機中點位移法簡介 1. 什么是隨機中點位移法&#xff1f;2. 應用領域 二、 Python 代碼實現 1. 導入必要的庫2. 函數定義&#xff1a;隨機中點位移法核心邏輯3. 設置隨機數種子4. 初始化二維裂隙面5. 初始化網格的四個頂點…

mysql之組內排序ROW_NUMBER()函數

有個需求&#xff0c;需要組內排序&#xff0c;之前似乎從未接觸過此類排序&#xff0c;故查詢了一下&#xff0c;記錄sql執行結果。 表如下&#xff1a; play_log: 日期 (fdate)用戶 ID (user_id)歌曲 ID (song_id)2022-01-081000002022-01-161000002022-01-201000002022-0…

Android TV端彈出的PopupWindow沒有獲取焦點

在 TV 開發中&#xff0c;焦點管理是通過 Focus Navigation 實現的&#xff0c;PopupWindow 默認不接受焦點&#xff0c;導致遙控器無法選擇彈窗內的控件。這是因為 PopupWindow 默認不會將焦點傳遞到其內容視圖上。 要解決問題&#xff0c;可以通過以下步驟調整 PopupWindow …

活動預告 | Microsoft Power Platform 在線技術公開課:實現業務流程自動化

課程介紹 參加“Microsoft Power Platform 在線技術公開課&#xff1a;實現業務流程自動化”活動&#xff0c;了解如何更高效地開展業務。參加我們舉辦的本次免費培訓活動&#xff0c;了解如何借助 Microsoft AI Builder 和 Power Automate 優化工作流。結合使用這些工具可以幫…

FPGA(二)組成結構基礎內容

1. FPGA的基本結構 FPGA主要由以下部分組成&#xff1a; &#xff08;1&#xff09;可編程邏輯單元&#xff08;CLB&#xff09;&#xff1a;CLB是FPGA中最基本的邏輯單元&#xff0c;由查找表&#xff08;LUT&#xff09;和觸發器組成&#xff0c;可實現任意邏輯功能。查找表…

LLM(十二)| DeepSeek-V3 技術報告深度解讀——開源模型的巔峰之作

近年來&#xff0c;大型語言模型&#xff08;LLMs&#xff09;的發展突飛猛進&#xff0c;逐步縮小了與通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 團隊最新發布的 DeepSeek-V3&#xff0c;作為一款強大的混合專家模型&#xff08;Mixture-of-Experts, MoE&a…

el-pagination 為什么只能展示 10 條數據(element-ui@2.15.13)

好的&#xff0c;我來幫你分析前端為什么只能展示 10 條數據&#xff0c;以及如何解決這個問題。 問題分析&#xff1a; pageSize 的值&#xff1a; 你的 el-pagination 組件中&#xff0c;pageSize 的值被設置為 10&#xff1a;<el-pagination:current-page"current…

TCP網絡編程(一)—— 服務器端模式和客戶端模式

這篇文章將會編寫基本的服務器網絡程序&#xff0c;主要講解服務器端和客戶端代碼的原理&#xff0c;至于網絡名詞很具體的概念&#xff0c;例如什么是TCP協議&#xff0c;不會過多涉及。 首先介紹一下TCP網絡編程的兩種模式&#xff1a;服務器端和客戶端模式&#xff1a; 首先…

C# 設計模式(行為型模式):責任鏈模式

C# 設計模式&#xff08;行為型模式&#xff09;&#xff1a;責任鏈模式 責任鏈模式&#xff08;Chain of Responsibility Pattern&#xff09;是一種行為型設計模式&#xff0c;用于讓多個對象有機會處理同一個請求&#xff0c;避免請求發送者與接收者之間的耦合。它通過將請…

在K8S中,如何部署kubesphere?

在Kubernetes集群中&#xff0c;對于一些基礎能力較弱的群體來說K8S控制面板操作存在一定的難度&#xff0c;此時kubesphere可以有效的解決這類難題。以下是部署kubesphere的操作步驟&#xff1a; 操作部署&#xff1a; 1. 部署nfs共享存儲目錄 yum -y install nfs-server e…

CSS系列(43)-- Anchor Positioning詳解

前端技術探索系列&#xff1a;CSS Anchor Positioning詳解 &#x1f3af; 致讀者&#xff1a;探索智能定位的藝術 &#x1f44b; 前端開發者們&#xff0c; 今天我們將深入探討 CSS Anchor Positioning&#xff0c;這個強大的元素定位特性。 基礎概念 &#x1f680; 錨點設…

Python判別不同平臺操作系統調用相應的動態庫讀寫NFC

本示例使用的發卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bV0E4YV&ftt&id615391857885 import sys import struct # struct的pack函數把任意數據類型變成字符串 import ctypes # 調用DLL動態庫要有這個引用if sys.platform…

樹莓派之旅-第一天 系統的燒錄和設置

自言自語&#xff1a; 在此記錄一下樹莓派的玩法。以后有錢了買點來玩啊草 系統的安裝燒錄 系統下載 樹莓派官網&#xff1a;https://www.raspberrypi.com/ 首頁點擊SoftWare進入OS下載頁面 這里是安裝工具&#xff1a;安裝工具負責將系統鏡像安裝到sd卡中 點擊下載符合自己…

商用車自動駕駛,迎來大規模量產「臨界點」?

商用車自動駕駛&#xff0c;正迎來新的行業拐點。 今年初&#xff0c;交通部公開發布AEB系統運營車輛標配征求意見稿&#xff0c;首次將法規限制條件全面放開&#xff0c;有望推動商用車AEB全面標配&#xff0c;為開放場景的商用車智能駕駛市場加了一把火。 另外&#xff0c;…

人工智能及深度學習的一些題目

1、一個含有2個隱藏層的多層感知機&#xff08;MLP&#xff09;&#xff0c;神經元個數都為20&#xff0c;輸入和輸出節點分別由8和5個節點&#xff0c;這個網絡有多少權重值&#xff1f; 答&#xff1a;在MLP中&#xff0c;權重是連接神經元的參數&#xff0c;每個連接都有一…

Solon 加入 GitCode:助力國產 Java 應用開發新飛躍

在當今數字化快速發展的時代&#xff0c;Java 應用開發框架不斷演進&#xff0c;開發者們始終在尋找更快、更小、更簡單的解決方案。近期&#xff0c;Solon 正式加入 GitCode&#xff0c;為廣大 Java 開發者帶來全新的開發體驗&#xff0c;尤其是在國產應用開發進程中&#xff…

VScode 只能運行c,運行不了c++的解決問題

原文鏈接&#xff1a;Vscode只能運行c&#xff0c;運行不了c的解決方法 VScode 只能運行c&#xff0c;運行不了c&#xff0c;怎么回事呢&#xff0c;解決問題&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 這樣之后 要重啟VScode&#xff0c;點擊鏈接…

Ansible Jinja2 語法簡介及使用

1、Jinja2 介紹 Jinja2 是基于 python 的模板引擎&#xff0c;功能比較類似于 PHP 的 smarty&#xff0c;J2ee 的 Freemarker和velocity。它能完全支持unicode&#xff0c;并具有集成的沙箱執行環境&#xff0c;應用廣泛。 jinja2使用BSD授權 Jinja2的語法是由 variables(變量…