【設計模式 01】單例模式

單例模式,是一種創建型設計模式,他的核心思想是保證一個類只有一個實例(即,在整個應用程序中,只存在該類的一個實例對象,而不是創建多個相同類型的對象),并提供一個全局訪問點來訪問這個實例(即,其他類只能通過一個,可以是靜態方法,來獲取到這個唯一實例)。

優勢:因為只有一個實例,既避免了多次創建相同的對象,節省了系統資源。多個類,也就是模塊之間可以通過單例實例來共享數據;同時方便我們站在全局的角度控制唯一實例的訪問(即,可以嚴格的控制客戶怎樣訪問它、何時訪問他);此外,單例模式還允許只在需要時才進行實例化,即所謂的懶加載,以提高程序的性能。

實現一個單例設計模式需要滿足以下的基本要求首先,任何外部代碼不能夠隨意創建實例,也就意味著類的構造函數只能私有;其次,任何外部代碼也不能夠隨意訪問實例中的任何資源,也就意味著所有的靜態實例變量須是私有的;最后,需要設置一個公有的靜態方法,以便外部能夠獲取到實例的內部資源。

單例模式的實現方式有:懶漢式(只有在遇到請求實例時才會創建一個實例,并且如果已經創建過,就會返回已有的實例)、餓漢式(類加載時就已經完成了實例的創建,不管創建的實例在后面會不會使用,先創建再說)等。

在多線程環境下,由于餓漢式在程序啟動階段就完成實例的初始化,因此不存在多個線程同時嘗試初始化實例的問題;但是懶漢式中多個線程同時訪問 GetInstance() 方法,并且在同一時刻檢測到實例沒有被創建(只要線程切換足夠頻繁就有可能發生),就可能會同時創建實例,從而導致多個實例被創建,(好比你和小明都發現家里每米了,在你們沒有相互通知的情況下,都會去超市買一袋米,這樣就重復購買了,違背了單例模式)這種情況下我們可以采用一些同步機制,例如使用互斥鎖來確保在任何時刻只有一個線程能夠執行實例的創建。

以下是單例設計模式的基本寫法,以Java代碼為例

  • 餓漢式:
public class Singleton {private static final Singleton instance = new Singleton(); // 類加載時就被創建private Singleton() {// 私有構造方法,防止外部實例化}public static Singleton getInstance() {return instance;}
} 
  • 懶漢式 + 互斥鎖:
public class Singleton {private static final Singleton instance;private Singleton() {// 私有構造方法,防止外部實例化}public static synchronized Singleton getInstance() {if (instance == null) {instance == new Singleton();}return instance;}
} 
  • 懶漢式 + 雙重檢查鎖提高性能:
public class Singleton {private static final Singleton instance;private Singleton() {// 私有構造方法,防止外部實例化}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance == new Singleton();}}}return instance;}
} 

在Java中,關鍵字synchronized用于實現線程的同步。

首先,synchronized可以用來修飾方法,表示該方法在同一時間只能被一個線程訪問。當一個線程訪問該方法時,其他線程必須等待該線程執行完畢才能訪問該方法。

其次,synchronized還可以用來修飾代碼塊。當多個線程需要訪問共享資源時,可以使用synchronized來保證同一時間只有一個線程可以訪問該資源。synchronized代碼塊使用一個對象作為鎖,當一個線程進入synchronized代碼塊時,會嘗試獲取該對象的鎖,如果鎖被其他線程占用,則該線程被阻塞,直到鎖被釋放。

synchronized的作用是避免多個線程對共享資源的并發訪問導致的數據不一致或者錯誤。通過使用synchronized,可以保證在同一時間只有一個線程對共享資源進行訪問,從而保證了線程安全。

"類.class"是Java編程中的一種語法結構,用于獲取某個類的Class對象。在Java中,每個類都對應一個Class對象,該對象包含了有關類的結構、字段、方法等信息,可以在程序運行時通過反射機制來訪問和操作類的成員。

通過類名后面添加".class",可以獲得該類的Class對象。例如,"String.class"返回String類的Class對象,"Integer.class"返回Integer類的Class對象。

使用Class對象可以進行一些操作,比如實例化對象、訪問類的靜態成員、獲取類的父類和接口等。

請注意,類.class只能用于獲取該類的Class對象,不能用于實例化這個類的對象。要實例化一個類的對象,可以使用Class對象中的newInstance()方法或者使用構造函數來創建對象。

總結一下,我們應當什么時候使用單例設計模式:

  1. 如果多個模塊都需要共享某一種資源,例如一個全局的配置管理器來存儲管理配置信息、管理數據庫連接池信息等,可以使用單例設計模式。
  2. 如果創建對象本身就比較消耗資源,而且可能在整個程序中都不一定會使用,就可以使用單例模式中的懶加載;
  3. 有些場景中只需要一個實例就足以協調所有行為,創建多個實例沒有必要甚至會導致不好的后果,例如管理應用程序中的緩存、管理線程池。

管理應用程序中的緩存只需要一個緩存實例的原因是為了保持數據的一致性和避免沖突。

當應用程序使用多個緩存實例時,可能會導致以下問題:

  1. 數據一致性:如果多個緩存實例各自獨立管理數據,那么在不同實例中的數據可能會不一致。當更新或刪除數據時,如果沒有及時同步所有的緩存實例,可能導致數據的不一致性,從而引發潛在的問題。

  2. 資源浪費:每個緩存實例都需要占用內存和其他資源,如果使用多個緩存實例,會造成資源的浪費。而只使用一個緩存實例可以更有效地利用資源。

  3. 緩存沖突:多個緩存實例可能會導致相同的數據被同時緩存在不同的實例中,從而造成緩存沖突。如果多個實例同時讀寫相同的數據,可能會引發并發問題,影響應用程序的性能和正確性。

通過只使用一個緩存實例,可以確保數據的一致性,并最大程度地節省資源。可以使用單例模式來創建和管理緩存實例,確保應用程序中只存在一個緩存對象。這樣可以簡化緩存管理的操作,提高系統的可靠性和性能。

【設計模式專題之單例模式】1.小明的購物車

?CPP版本:

#include <iostream>
#include <vector>
#include <map>using namespace std;class ShoppingCartManager {
public:// 獲取購物車實例static ShoppingCartManager& getInstance() {static ShoppingCartManager instance;return instance;}// 添加商品到購物車void addToCart(const string& itemName, int quantity) {if (cart.find(itemName) == cart.end()) {order.push_back(itemName);}cart[itemName] += quantity;}// 查看購物車void viewCart() const {for (const auto& itemName : order) {cout << itemName << " " << cart.at(itemName) << endl; // 不能使用cart[itemName],因為處在一個const方法,不能有修改變量值的格式出現。}}private:// 私有構造函數ShoppingCartManager() {}// 購物車存儲商品和數量的映射map<string, int> cart;// 記錄加入購物車的順序vector<string> order;
};int main() {string itemName;int quantity;while (cin >> itemName >> quantity) {// 獲取購物車實例并添加商品ShoppingCartManager& cart = ShoppingCartManager::getInstance();cart.addToCart(itemName, quantity);}// 輸出購物車內容const ShoppingCartManager& cart = ShoppingCartManager::getInstance();cart.viewCart();return 0;
}

在C++中,static關鍵字可以有多種作用

  1. 靜態變量(Static Variables):在函數內使用static關鍵字,可以創建靜態變量。靜態變量在函數調用結束后仍然存在,并且在下一次調用函數時保持其值不變。這使得靜態變量在需要記住上一次函數調用結果或在多次調用之間共享數據時非常有用。

  2. 靜態成員變量(Static Member Variables):在類內部使用static關鍵字,可以創建靜態成員變量。靜態成員變量屬于類本身而不是類的實例,因此在不創建類的對象時也可以訪問和修改它們。靜態成員變量在類的所有實例之間共享數據。

  3. 靜態函數(Static Functions):在類內部使用static關鍵字,可以創建靜態函數。靜態函數不依賴于類的實例,因此可以直接通過類名調用,無需創建類的對象。靜態函數主要用于處理和類本身相關的操作,而不是與類的實例數據交互。

  4. 靜態類(Static Classes):在C++中,可以將類聲明為static類。靜態類的成員函數和成員變量都必須是靜態的,而且無法創建靜態類的對象。靜態類主要用于實現一些全局可訪問的、不需要創建對象的功能,類似于命名空間的作用。

總的來說,C++中的static關鍵字可以用于創建靜態變量、靜態成員變量、靜態函數以及靜態類,它們都具有特定的作用和用途。

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

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

相關文章

java012 - Java集合基礎

1、集合基礎 1.1 集合概述 引用數據類型包括&#xff1a;類、接口、數組[] 1.2 ArrayList構造和添加方法 代碼&#xff1a; 空集合對象&#xff1a;[] add() add(int index,E element): 1.3 ArrayList集合常用方法

計算機體系結構安全:對體系結構如何支持安全機制進行調研

一、體系結構支持信任建立和主動防御的技術&#xff1a; 可信3.0 二、體系結構怎么更好的支持信任建立和主動防御 2.1 支持信任建立 一、以手機芯片舉例&#xff0c;用智能手機的芯片作為信任根&#xff0c;確保應用程序和敏感數據受到保護。 二、啟動時驗證操作系統和應用…

Stable Diffusion 模型分享:Henmix_Real(人像、真實、寫真、亞洲面孔)

本文收錄于《AI繪畫從入門到精通》專欄,專欄總目錄:點這里。 文章目錄 模型介紹生成案例案例一案例二案例三案例四案例五案例六案例七案例八下載地址模型介紹 作者述:這個模型試圖改

深入理解算法的空間復雜度

算法一&#xff1a;逐步遞增型 void Loveyou(int n)//n為問題規模 {int i1;while(i<n){i;printf("I love you %d\n",i);}printf("I love you more than %d\n",n);//5 } int main() {Loveyou(3000);return 0; } 無論問題規模怎么變&#xff0c;算法運行…

Springboot教程(五)——單元測試

idea中一般使用JUnit進行單元測試 基本使用 我們可以在idea的test文件夾下的XXXXApplicationTests內進行單元測試&#xff1a; 可以在Test標注的方法上寫測試代碼&#xff1a; SpringBootTest class C0101ApplicationTests {Testfun contextLoads() {println("Hello …

基礎二分學習筆記

模板 : 個人傾向第一種 ; 整數二分 : 最大化查找 : 可行區域在左側 : 查找最后一個<q的數的下標 : int find(int q){// 查找最后一個 < q 的下標 int l 0 , r n 1 ;while(l 1 < r){int mid l r >> 1 ;if(a[mid]<q) l mid ;else r mid ;}return…

django settings.py STATICFILES_FINDERS 設置

STATICFILES_FINDERS 定義查找器后端以確保Django能夠正確地定位和提供靜態文件是很重要的. Django中的STATICFILES FINDERS設置是一個inder后端列表&#xff0c;它知道如何在不同的位置定位靜態文件。 它被Django的靜態文件處理系統用來在開發和部署過程中查找和收集靜態文件…

js json轉換成字符串

js中JSON數據轉換成字符串&#xff0c;可以使用JSON.stringify()方法。 var obj {name: "張三", age: 18, gender: "男"}; var jsonString JSON.stringify(obj); console.log(jsonString); // 輸出 {"name":"張三","age"…

土壤類型數據

國家地球系統科學數據中心

AGM CPLD (AGRV2K )的時鐘(外部時鐘和片上內部振蕩器)

AGM CPLD &#xff08;AGRV2K &#xff09;的時鐘(外部時鐘和片上內部振蕩器) 外部晶振 與 內部振蕩器&#xff1a; mcu 和 cpld 聯合編程時&#xff0c; 整顆芯片需要一顆外部晶振。 &#xff08;芯片有內部振蕩器&#xff0c; 但誤差較大&#xff0c; 校準后 5%以內誤差&…

216. 組合總和 III(力扣LeetCode)

文章目錄 216. 組合總和 III回溯算法 216. 組合總和 III 找出所有相加之和為 n 的 k 個數的組合&#xff0c;且滿足下列條件&#xff1a; 只使用數字1到9每個數字 最多使用一次 返回 所有可能的有效組合的列表 。該列表不能包含相同的組合兩次&#xff0c;組合可以以任何順序…

Electron通過預加載腳本從渲染器訪問Node.js

問題&#xff1a;如何實現輸出Electron的版本號和它的依賴項到你的web頁面上&#xff1f; 答案&#xff1a;在主進程通過Node的全局 process 對象訪問這個信息是微不足道的。 然而&#xff0c;你不能直接在主進程中編輯DOM&#xff0c;因為它無法訪問渲染器 文檔 上下文。 它們…

【軟考】數據庫的三級模式

目錄 一、概念1.1 說明1.2 數據庫系統體系結構圖 二、外模式三、概念模式四、內模式 一、概念 1.1 說明 1.數據的存儲結構各不相同&#xff0c;但體系結構基本上具有相同的特征&#xff0c;采用三級模式和兩級鏡像 2.數據庫系統設計員可以在視圖層、邏輯層和物理層對數據進行抽…

matplotlib散點圖

matplotlib散點圖 假設通過爬蟲你獲取到了北京2016年3, 10月份每天白天的最高氣溫(分別位于列表a, b), 那么此時如何尋找出氣溫和隨時間(天)變化的某種規律? from matplotlib import pyplot as pltx_3 range(1, 32) x_10 range(51, 82)y_3 [11,17,16,11,12,11,12,6,6,7,8…

試手一下CameraX(APP)

書接上回。 首先還是看谷歌的官方文檔&#xff1a; https://developer.android.com/media/camera/camerax?hlzh-cn https://developer.android.com/codelabs/camerax-getting-started?hlzh-cn#1 注&#xff1a;這里大部分內容也來自谷歌文檔。 官方文檔用的是Kotlin&…

常用的字符字符串的讀取方法(C / C++)

一、字符 1、讀取單個字符&#xff1a;直接讀取 //輸入a //讀取 char x; scanf("%c",&x); 2、讀取帶空格的字符 h h h 按格式書寫格式化字符串即可 char a,b,c; scanf("%c %c %c",&a,&b,&c); 3、 處理字符間的換行符 假設要讀取以…

Day14:信息打點-主機架構蜜罐識別WAF識別端口掃描協議識別服務安全

目錄 Web服務器&應用服務器差異性 WAF防火墻&安全防護&識別技術 蜜罐平臺&安全防護&識別技術 思維導圖 章節知識點 Web&#xff1a;語言/CMS/中間件/數據庫/系統/WAF等 系統&#xff1a;操作系統/端口服務/網絡環境/防火墻等 應用&#xff1a;APP對象/…

小程序圖形:echarts-weixin 入門使用

去官網下載整個項目&#xff1a; https://github.com/ecomfe/echarts-for-weixin 拷貝ec-canvs文件夾到小程序里面 index.js里面的寫法 import * as echarts from "../../components/ec-canvas/echarts" const app getApp(); function initChart(canvas, width, h…

Vscode 使用SSH遠程連接樹莓派的教程(解決卡在Downloading with wget)

配置Vscode Remote SSH 安裝OpenSSH 打開Windows開始頁面&#xff0c;直接進行搜索PowerShell&#xff0c;打開第一個Windows PowerShell&#xff0c;點擊以管理員身份運行 輸入指令 Get-WindowsCapability -Online | ? Name -like OpenSSH* 我是已經安裝好了&#xff0c;…

學會玩游戲,智能究竟從何而來?

最近在讀梅拉妮米歇爾《AI 3.0》第三部分第九章&#xff0c;談到學會玩游戲&#xff0c;智能究竟從何而來&#xff1f; 作者: [美] 梅拉妮米歇爾 出版社: 四川科學技術出版社湛廬 原作名: Artificial Intelligence: A Guide for Thinking Humans 譯者: 王飛躍 / 李玉珂 / 王曉…