單例模式詳解:概念與實用技巧

目錄

  • 單例模式
    • 單例模式結構
    • 單例模式適用場景
    • 單例模式優缺點
    • 練手題目
      • 題目描述
      • 輸入描述
      • 輸出描述
      • 輸入示例
      • 輸出示例
      • 提示信息
      • 題解

單例模式

單例模式是一種創建型設計模式, 讓你能夠保證一個類只有一個實例, 并提供一個訪問該實例的全局節點。

  • 只有一個實例的意思是,在整個應用程序中,只存在該類的一個實例對象,而不是創建多個相同類型的對象。

  • 全局訪問點的意思是,為了讓其他類能夠獲取到這個唯一實例,該類提供了一個全局訪問點(通常是一個靜態方法),通過這個方法就能獲得實例。

單例模式結構

  • 私有的構造函數:防止外部代碼直接創建類的實例

  • 私有的靜態實例變量:保存該類的唯一實例

  • 公有的靜態方法:通過公有的靜態方法來獲取類的實例

在這里插入圖片描述

單例模式通用代碼

單例模式的實現方式有多種,包括懶漢式、餓漢式等。

  • 餓漢式指的是在類加載時就已經完成了實例的創建,不管后面創建的實例有沒有使用,先創建再說,所以叫做 “餓漢”。

  • 而懶漢式指的是只有在請求實例時才會創建,如果在首次請求時還沒有創建,就創建一個新的實例,如果已經創建,就返回已有的實例,意思就是需要使用了再創建,所以稱為“懶漢”。

餓漢模式

//單例類通過'getSingleton(獲取實例)'方法進行定義,讓客戶端全局獲得該對象實例
public class Singleton{// 保存單例實例成員變量必須被聲明為靜態類型
private static final Singleton singleton=new Singleton();// 單例的構造函數必須永遠是私有類型,以防止使用`new`運算符直接調用構造方法。限制產生多個對象
private Singleton(){}//通過該方法獲得實例對象
public static Singleton getSingleton(){
return singleton;}
//類中其他方法,盡量是static
public static void doSomething(){}
}

懶漢模式

public class Singleton {private static Singleton instance;private Singleton() {// 私有構造方法,防止外部實例化}// 使用了同步關鍵字來確保線程安全, 可能會影響性能public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

在懶漢模式的基礎上,可以使用雙重檢查鎖來提高性能。

public class Singleton {private static volatile Singleton instance;private Singleton() {// 私有構造方法,防止外部實例化}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

有上限的多例模式,它是單例模式的一種擴展,采用有上限的多例模式,我們可以在設計時決定在內存中有多少個實例,方便系統進行擴展,修正單例可能存在的性能問題,提供系統的響應速度。

public class Singleton{private static int maxNum=3;//最多產生3個實例數量private static ArrayList<Singleton> List=new ArrayList<Singleton>();private static int count=0;//當前皇帝序列號static{for(int i=0;i<maxNum;i++){List.add(new Singleton());}}private Singleton(){}private static Singleton getInstance(){Random random=new Random();count=random.nextInt(maxNum);return List.get(count);}}

單例模式適用場景

  1. 如果程序中的某個類對于所有客戶端只有一個可用的實例, 可以使用單例模式。

    單例模式禁止通過除特殊構建方法以外的任何方式來創建自身類的對象。 該方法可以創建一個新對象, 但如果該對象已經被創建, 則返回已有的對象。

  2. 如果你需要更加嚴格地控制全局變量, 可以使用單例模式。

    單例模式與全局變量不同, 它保證類只存在一個實例。 除了單例類自己以外, 無法通過任何方式替換緩存的實例。

在這里插入圖片描述

識別方法: 單例可以通過返回相同緩存對象的靜態構建方法來識別。

單例模式優缺點

單例模式優點:

  • 你可以保證一個類只有一個實例。

  • 你獲得了一個指向該實例的全局訪問節點。

  • 僅在首次請求單例對象時對其進行初始化。

單例模式缺點:

  • 違反了單一職責原則。 該模式同時解決了兩個問題。

  • 單例模式一般沒有接口,擴展很困難,若要擴展,除了修改代碼基本上沒有第二種途徑可以實現。

  • 單例模式可能掩蓋不良設計, 比如程序各組件之間相互了解過多等。

  • 該模式在多線程環境下需要進行特殊處理, 避免多個線程多次創建單例對象。

  • 單例的客戶端代碼單元測試可能會比較困難, 因為許多測試框架以基于繼承的方式創建模擬對象。 由于單例類的構造函數是私有的, 而且絕大部分語言無法重寫靜態方法, 所以你需要想出仔細考慮模擬單例的方法。 要么干脆不編寫測試代碼, 或者不使用單例模式。

練手題目

題目描述

小明去了一家大型商場,拿到了一個購物車,并開始購物。請你設計一個購物車管理器,記錄商品添加到購物車的信息(商品名稱和購買數量),并在購買結束后打印出商品清單。(在整個購物過程中,小明只有一個購物車實例存在)。

輸入描述

輸入包含若干行,每行包含兩部分信息,分別是商品名稱和購買數量。商品名稱和購買數量之間用空格隔開。

輸出描述

輸出包含小明購物車中的所有商品及其購買數量。每行輸出一種商品的信息,格式為 “商品名稱 購買數量”。

輸入示例

Apple 3 Banana 2 Orange 5

輸出示例

Apple 3 Banana 2 Orange 5

提示信息

本道題目請使用單例設計模式, 使用私有靜態變量來保存購物車實例。 使用私有構造函數防止外部直接實例化。

題解

1.簡單單例模式實現。

import java.util.Scanner;
import java.util.ArrayList;class ShoppingCart {private static ShoppingCart instance = new ShoppingCart();private static ArrayList<String> productNames = new ArrayList<>();private static ArrayList<Integer> productQuantities = new ArrayList<>();private ShoppingCart() {}public static ShoppingCart getInstance() {return instance;}public void Add(String name, int quantity) {productNames.add(name);productQuantities.add(quantity);System.out.println(name + " " + quantity);}
}public class Main {public static void main(String[] args) {ShoppingCart cart = ShoppingCart.getInstance();Scanner scanner = new Scanner(System.in);String inputLine;while (scanner.hasNextLine()) {inputLine = scanner.nextLine();if ("exit".equalsIgnoreCase(inputLine)) {break;}String[] parts = inputLine.split(" ");if (parts.length == 2) {String name = parts[0];int quantity;try {quantity = Integer.parseInt(parts[1]);cart.Add(name, quantity);} catch (NumberFormatException e) {System.out.println("輸入錯誤,請重新輸入");}} else {System.out.println("輸入錯誤,請重新輸入");}}scanner.close();}
}

2.在懶漢模式的基礎上,可以使用雙重檢查鎖來提高性能。

import java.util.Scanner;  
import java.util.ArrayList;  class ShoppingCart {// 購物車類的單例實例變量,使用volatile關鍵字確保線程安全private static volatile ShoppingCart instance;// 存儲商品名稱private static ArrayList<String> productNames = new ArrayList<>();// 存儲商品數量private static ArrayList<Integer> productQuantities = new ArrayList<>();// 私有構造函數,防止外部直接創建ShoppingCart對象private ShoppingCart() {}// 獲取購物車單例實例的方法,確保線程安全public static ShoppingCart getInstance() {if (instance == null) {synchronized (ShoppingCart.class) {if (instance == null) {instance = new ShoppingCart();}}}return instance;}// 添加商品到購物車的方法public void Add(String name, int quantity) {productNames.add(name); productQuantities.add(quantity); System.out.println(name + " " + quantity);}
}public class Main {public static void main(String[] args) {ShoppingCart cart = ShoppingCart.getInstance(); Scanner scanner = new Scanner(System.in);  String inputLine;// 循環讀取用戶輸入,直到用戶輸入"exit"while (scanner.hasNextLine()) {inputLine = scanner.nextLine();if ("exit".equalsIgnoreCase(inputLine)) {break;}// 使用空格分割輸入的字符串,獲取商品名稱和數量String[] parts = inputLine.split(" ");// 確保輸入格式正確,即包含兩個部分:商品名稱和數量if (parts.length == 2) {// 商品名稱String name = parts[0];  // 商品數量int quantity; try {// 將第二部分轉換為整數quantity = Integer.parseInt(parts[1]);cart.Add(name, quantity);  } catch (NumberFormatException e) {// 如果轉換失敗,輸出錯誤信息System.out.println("轉換失敗,請重新輸入");}} else {// 如果輸入格式不正確,輸出錯誤信息System.out.println("如果輸入格式不正確,請重新輸入");}}scanner.close();}
}

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

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

相關文章

阿里巴巴店鋪電話采集軟件操作步驟解析

以下是一個簡單的程序&#xff0c;用于訪問1688店鋪并獲取店鋪信息&#xff1a; import requestsdef get_store_info(store_id):# 構建請求URLurl fhttps://detail.1688.com/offer/{store_id}.html# 發送GET請求response requests.get(url)# 如果請求成功if response.status…

震驚!運氣竟能如此放大!運氣的驚人作用,你了解嗎?

芒格&#xff1a;得到你想要的東西&#xff0c;最保險的辦法&#xff0c;就是讓自己配得上你想要的那個東西。今天仔細想了想這句話&#xff0c;他其實說的是無數成功人士的心聲 —— “我配得上&#xff01;” 美劇《絕命毒師》有個導演叫文斯吉里根&#xff08;Vince Gilliga…

注解【開發實踐】

文章目錄 一、注解概述1.1 什么是注解1.2 注解的作用1.3 一些特殊的注解 二、元注解2.1 Retention2.2 target2.3 Documented2.4 Inherited2.5 Repeatable 三、注解的使用3.1 定義注解3.2 編寫注解處理器3.3 注冊注解處理器 一、注解概述 1.1 什么是注解 注解&#xff08;Anno…

大疆2025校招內推

需要內推碼的請留言哦 期待你的加入

windows@資源管理器中的地址欄@訪問共享文件夾的各種方法@管理共享文件夾

文章目錄 資源管理器中的地址欄可以訪問什么訪問共享文件夾&#x1f47a;UNC路徑資源管理器打開共享文件夾純命令行方式訪問共享文件夾 共享文件夾相關操作查看所有已經共享的文件夾&#x1f47a;停止某個文件的共享 共享文件夾的訪問控制補充匿名訪問問題&#x1f60a;強制啟用…

集群限流sentinel實踐

參考&#xff1a; 集群模式 實踐 集群流控規則 其中 用一個專門的 ClusterFlowConfig 代表集群限流相關配置項&#xff0c;以與現有規則配置項分開&#xff1a; // 全局唯一的規則 ID&#xff0c;由集群限流管控端分配. private Long flowId;// 閾值模式&#xff0c;默認&…

吳恩達深度學習筆記:機器學習策略(2)(ML Strategy (2)) 2.5-2.6

目錄 第三門課 結構化機器學習項目&#xff08;Structuring Machine Learning Projects&#xff09;第二周&#xff1a;機器學習策略&#xff08;2&#xff09;(ML Strategy (2))2.5 數據分布不匹配時的偏差與方差的分析&#xff08;Bias and Variance with mismatched data di…

師從IEEE fellow|博士后加拿大阿爾伯塔大學成行

V老師指定申請加拿大&#xff0c;優先對方出資的博士后&#xff0c;如果外方無資助&#xff0c;也可以自籌經費&#xff0c;但要求必須是博士后頭銜。最終我們為其落實了加拿大阿爾伯塔大學的postdoctoral fellow&#xff08;博士后研究員&#xff09;&#xff0c;盡管是無薪職…

adb的使用

xcode&#xff1a;https://juejin.cn/post/7005854415420653604 安裝 https://zhuanlan.zhihu.com/p/662190715 使用 1.安卓手機打開開發者模式&#xff0c;并連接電腦 2.在mac終端輸入命令adb logcat | grep {tag_name}即可查看日志 常用命令&#xff1a; https://zhuan…

2024亞太杯中文賽數學建模選題建議及各題思路來啦!

大家好呀&#xff0c;2024年第十四屆APMCM亞太地區大學生數學建模競賽&#xff08;中文賽項&#xff09;開始了&#xff0c;來說一下初步的選題建議吧&#xff1a; 首先定下主基調&#xff0c; 本次亞太杯推薦大家選擇B題目。C題目難度較高&#xff0c;只建議用過kaiwu的隊伍…

倉頡——申請內測、環境搭建、編譯測試

2024年6月21日&#xff0c;華為倉頡正式公開發布。 不少同學看過倉頡白皮書后&#xff0c;都在找SDK從哪下載&#xff0c;HelloWorld怎么跑。倉頡公眾號也及時發布了內測的方式&#xff0c;我也親自走了一遍整個流程&#xff0c; 一&#xff0c;申請內測 關注“倉頡編程語言…

暗潮短視頻:成都柏煜文化傳媒有限公司

暗潮短視頻&#xff1a;涌動的新媒體力量 在數字化時代的浪潮中&#xff0c;短視頻以其獨特的魅力和無限的潛力&#xff0c;迅速成為新媒體領域的一股強大力量。而在這片繁榮的短視頻領域中&#xff0c;成都柏煜文化傳媒有限公司“暗潮短視頻”以其獨特的定位和深邃的內容&…

Beyond Low-frequency Information in Graph Convolutional Networks

推薦指數: #paper/??? #paper/&#x1f4a1; 發表于:AAAI21 簡稱:FAGCL 問題提出背景: GCN常常使用低頻信息,但是在現實中,不僅低頻信息重要,高頻信息頁重要 如上圖,隨著類間鏈接的增加,低頻信號的增強開始變弱,高頻信號的增強開始增加. 作者貢獻: 不僅低頻信號重要,高…

智能井蓋采集裝置 開啟井下安全新篇章

在現代城市的脈絡之下&#xff0c;錯綜復雜的管網系統如同城市的血管&#xff0c;默默支撐著日常生活的有序進行。而管網的監測設備大多都安裝在井下&#xff0c;如何給設備供電一直是一個難題&#xff0c;選用市電供電需經過多方審批&#xff0c;選用電池供電需要更換電池包&a…

MySQL表的練習

二、創建表 1、創建一個名稱為db_system的數據庫 create database db_system; 2、在該數據庫下創建兩張表&#xff0c;具體要求如下 員工表 user 字段 類型 約束 備注 id 整形 主鍵&#xff0c;自增長 id N…

Spring Boot項目(蒼穹)

Spring Boot 框架詳解 概述 Spring Boot 是一個基于 Spring 框架的工具&#xff0c;用于簡化 Spring 應用程序的開發。它通過提供默認配置和快速啟動機制&#xff0c;使開發者可以專注于業務邏輯&#xff0c;而不必過多關注配置和底層細節。Spring Boot 讓開發變得更加簡單、…

權限控制權限控制權限控制權限控制權限控制

1.權限的分類 視頻學習&#xff1a;https://www.bilibili.com/video/BV15Q4y1K79c/?spm_id_from333.337.search-card.all.click&vd_source386b4f5aae076490e1ad9b863a467f37 1.1 后端權限 1. 后端如何知道該請求是哪個用戶發過來的 可以根據 cookie、session、token&a…

Python pyecharts 模塊

pyecharts 是一個基于 ECharts.js 的 Python 可視化庫&#xff0c;用于生成各種類型的交互式圖表和數據可視化。它支持多種常見的圖表類型&#xff0c;如折線圖、柱狀圖、散點圖、餅圖等&#xff0c;可以在 Web 頁面中呈現&#xff0c;并且具有豐富的配置選項和樣式定制能力。 …

qt c++ 實現服務注冊、發布服務,最后被成功后回調

在Qt中實現服務注冊、發布服務&#xff0c;并在服務成功發布后執行回調&#xff0c;可以通過使用Qt的QLocalServer和QLocalSocket來實現本地服務通信&#xff0c;或者使用網絡服務如QTcpServer和QTcpSocket進行網絡服務的發布與發現。這里我們以本地服務為例來說明。 實現本地…

WIN32核心編程 - 進程操作(一) 進程基礎 - 創建進程 - 進程句柄

公開視頻 -> 鏈接點擊跳轉公開課程博客首頁 -> 鏈接點擊跳轉博客主頁 目錄 進程基礎 進程的定義與概念 進程的組成 創建進程 可執行文件 CreateProces 執行流程 GetStartupInfo 進程終止 進程句柄 創建進程 打開進程 進程提權 內核模擬 回溯對象 自身進…