單例模式-Python示例

單例模式

單例模式(Singleton Pattern)是設計模式中一種創建型模式,廣泛應用于軟件開發中。一以下以故事化的方式,結合詳細的技術講解,介紹單例模式的背景、定義、適用場景,并提供python的示例代碼。

故事1:皇帝的玉璽

在古代的龍國,皇帝是國家的唯一最高統治者,象征權力的玉璽也只有一塊。無論多少大臣、多少事務需要蓋章,所有人都必須使用同一塊玉璽。皇帝下令:這塊玉璽是獨一無二的,不能有第二塊!誰敢私自造玉璽,格殺勿論!
于是,為了確保玉璽的唯一性,皇帝派專人保管,任何人需要蓋章時,都得向保管者申請使用這塊玉璽。這樣,全國上下都用同一塊玉璽,保證了權力的統一性和一致性。
有一天,鄰國的使者來訪,帶來了一個問題:如果多個大臣同時需要蓋章,玉璽如何分配?皇帝想了想,決定讓保管者記錄玉璽的使用情況,確保每次只有一個人能拿到玉璽使用,其他人必須排隊等待。這不僅保證了玉璽的唯一行,還避免了混亂。

這個故事中的玉璽,就是單例模式的完全體現:全局唯一、受控訪問。

在古代的一個小村莊里,有一口古老的“智慧之井”,據說井水能賦予飲用者無窮的智慧。村民們都想喝到井水,但村長發現,如果每個人都隨意打水,井水很快就會干涸。于是,村長宣布:全村只能有一個“水官”負責管理井水,每天只打一桶水,供大家享用。這個“水官”就是全村唯一的井水管理者,任何時候只有他能接觸到井水,確保井水不會被濫用。

這個故事就像程序設計中的單例模式。在軟件開發中,有些資源(如數據庫連接、配置文件、線程池等),就像“智慧之井”,如果每次都創建新實例,會浪費資源或導致沖突。單例模式就像村里的“水官”,確保全局只有一個實例,統一管理資源。

單例模式是什么?

單例模式(Singleton Pattern)是一種創建型設計模式,它保證一個類只有一個實例,并提供一個全局訪問點來獲取該實例。單例模式的核心是控制對象的創建過程,確保系統中該類的對象始終只有一個。

解決什么樣的問題

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

1、資源共享:避免多次創建對象導致的資源浪費(如數據庫連接池、日志對象)

2、全局狀態管理:需要一個全局唯一的對象來協調系統行為(如配置管理器、計數器)

3、控制并發訪問:防止多個實例同時操作同一資源導致的數據不一致(如線程池)

4、減少系統開銷:避免頻繁創建和銷毀對象,提升性能

適用場景

單例模式適用于以下場景

1、需要全局唯一實例的資源

  • 配置文件管理器:整個應用共享同一份配置
  • 日志記錄器:統一管理日志輸出
  • 數據庫連接池:避免重復創建連接

2、需要控制資源訪問

  • 線程池:統一管理線程資源
  • 緩存管理器:全局共享緩存數據

3、需要全局協調的場景

  • 計數器:記錄系統中某些操作的次數
  • 狀態管理器:維護系統的全局狀態

優缺點

優點:

  • 節省資源:只創建一個實例,減少內存和系統開銷
  • 全局訪問點:提供統一的訪問入口,方便管理
  • 嚴格控制實例:避免多實例帶來的沖突或數據不一致

缺點

  • 單點故障:如果單例對象出現問題,可能影響整個系統
  • 難以測試:單例的全局狀態可能導致單元測試復雜化
  • 違反單一職責原則:單例既負責自身邏輯,又負責實例管理
  • 擴展性差:難以繼承或修改,因為單例通常是靜態的

實現方式

單例模式有幾種常見實現方式

  • 餓漢式:類加載時酒創建實例(線程安全,但可能浪費資源)
  • 懶漢式:需要時才創建實例(需考慮線程安全)
  • 雙檢鎖:懶漢式的線程安全優化
  • 靜態內部類:結合餓漢式和懶漢式的優點(Java常用)
  • 模塊級單例:Python的模塊天然支持單例

Python示例代碼

以下展示幾種Python實現單例模式的方式,并附上詳細注釋,為了貼合故事,代碼以“皇帝的玉璽”作為類名

方式1:經典懶漢式(線程不安全)

class ImperialSeal:# 私有類變量,存儲唯一實例_instance = Nonedef __new__(cls):# 如果實例不存在,則創建if cls._instance is None:cls._instance = super().__new__(cls)return cls._instancedef __init__(self):# 出事話只執行一次,防止重復初始化if not hasattr(self, '_initialized'):self._initialized = Trueself.seal_name = "Dragon Seal"def use_seal(self):print(f"Using the {self.seal_name} to stamp a decree!")# 測試代碼
if __name__ == "__main__":seal1 = ImperialSeal()seal2 = ImperialSeal()# Trueprint(f"Same instance: {seal1 is seal2}")# Using the Dragon Seal to stamp a decree!seal1.use_seal()

說明

  • new方法控制實例創建,確保只有一個實例
  • init適用_initialized防止重復初始化_
  • 缺點:多線程環境下可能創建多個實例(線程不安全)

方式2:線程安全的懶漢式(使用鎖)

import threading
from threading import Lockclass ImperialSeal:# 私有類變量,存儲唯一實例_instance = None# 鎖,用于線程安全_lock = Lock()def __new__(cls):with cls._lock:if cls._instance is None:cls._instance = super().__new__(cls)return cls._instancedef __init__(self):if not hasattr(self, '_initialized'):self._initialized = Trueself.seal_name = "Dragon Seal"def use_seal(self):print(f"Using the {self.seal_name} to stamp a decree!")def create_seal():seal = ImperialSeal()print(f"Created seal: {id(seal)}")# 測試代碼
if __name__ == "__main__":threads = [threading.Thread(target=create_seal) for _ in range(5)]for t in threads:t.start()for t in threads:t.join()seal1 = ImperialSeal()seal2 = ImperialSeal()# Trueprint(f"Same instance: {seal1 is seal2}")# Using the Dragon Seal to stamp a decree!seal1.use_seal()

說明

  • 使用threading.Lock確保多線程環境下之創建一次實例
  • with cis.lock保證線程安全,但加鎖可能影響性能
  • 適合多線程場景,如web服務器中的全局配置管理

方式3:Python模塊單例

Python的模塊本身是天然的單例,因為模塊只加載一次。以下展示如何利用模塊實現單例

# 單例模式 - 模塊級單例實現
# 通過在模塊級別定義全局唯一實例來實現單例模式class ImperialSeal:def __init__(self):self.seal_name = "Dragon Seal"  # 玉璽名稱def use_seal(self):print(f"使用 {self.seal_name} 蓋章于圣旨!")  # 使用玉璽蓋章# 定義全局唯一實例
seal = ImperialSeal()# 測試代碼
if __name__ == "__main__":# 直接引用模塊中的 seal 實例,模擬多次導入seal1 = sealseal2 = sealprint(f"是否為同一實例: {seal1 is seal2}")  # 應輸出 Trueseal1.use_seal()  # 輸出: 使用 Dragon Seal 蓋章于圣旨!

說明

  • Python模塊在程序運行期間只加載一次,seal變量天然全局唯一
  • 簡單高效,無需顯式控制實例創建
  • 適合簡單場景,但不適合需要復雜初始化邏輯的情況

故事續篇:玉璽的挑戰

龍國的玉璽管理逐漸復雜,大臣們發現

  • 并發問題:多個大臣同時申請玉璽,導致蓋章混亂(線程安全問題)
  • 測試麻煩:玉璽的全局性讓模擬測試變的困難(單例的全局狀態問題)
  • 擴展需求:鄰國提議聯合使用玉璽,但玉璽無法輕易擴展(單例擴展性差)

皇帝召集智囊團,決定

  • 使用“鎖匠”(線程鎖)確保玉璽一次只被一人使用(線程安全單例)
  • 編寫“玉璽副本”用于測試(依賴注入替換單例)
  • 對于新需求,考慮“多玉璽模式”(非單例設計)

這個故事告訴我們:單例模式雖然簡單有效,但需謹慎使用,避免濫用導致維護困難

適用場景舉例

1、日志管理器:全局唯一的日志對象,確保日志寫入一致

import logging
# logging 模塊天然單例
logger = logging.getLogger("app")

2、數據庫連接池

import pymysqlclass DBConnection:_instance = Nonedef __new__(cls):if cls._instance is None:cls._instance = super().__new__(cls)cls._instance.conn = pymysql.connect(host="localhost",user="root",password="123456",database="test")return cls._instance

3、配置管理:全局讀取配置,避免重復加載

class Config:_instance = Nonedef __new__(cls):if cls._instance is None:cls._instance = super(Config, cls).__new__(cls)cls._instance.settings = {"api_key": "12345", "timeout": 30}return cls._instance

注意事項

  • 線程安全:多線程環境下,有限適用鎖或模塊級單例
  • 測試問題:單例的全局狀態可能影響單元測試,建議結合依賴注入
  • 濫用風險:不宜將所有全局對象都用單例,可能導致單例過多,增加復雜性
  • Python特性:Python的模塊機制天然支持單例,優先考慮模塊級單例以簡化代碼

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

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

相關文章

啥是 SaaS

https://www.youtube.com/watch?vnpcL7oRZQlI這個視頻講了什么東西, 什么 idea?好的,這個視頻內容非常棒,信息量很足。下面為你詳細總結視頻講了什么,以及核心的 Idea 是什么。 視頻核心 Idea 這個視頻講的是一位名叫 Leandro…

Spring Boot 工程啟動以后,我希望將數據庫中已有的固定內容,打入到 Redis 緩存中,請問如何處理?

在 Spring Boot 工程中,將數據庫中的固定內容預先加載到 Redis 緩存中可以通過以下步驟實現。這里假設你已經配置好了 Spring Data Redis 和數據庫(如 MySQL)的連接。 1. 添加依賴 首先,確保你的 pom.xml(Maven&…

springboot企業級項目開發之項目測試——集成測試!

集成測試 集成測試是指項目代碼在單元測試完成后進行的第二階段測試。集成測試的重點是在集成組件或單元之間交互時暴露缺陷,以保證不同模塊之間相互調用的正確性。在Spring Boot的項目集成測試中,將測試Controller和Dao的完整請求處理。應用程序在服務…

HTML 媒體(Media)

HTML 媒體(Media) 引言 HTML 媒體元素是構成現代網頁的重要組成部分,它允許我們在網頁中嵌入各種類型的媒體內容,如音頻、視頻、圖像等。這些元素不僅豐富了網頁的視覺效果,還提升了用戶體驗。本文將詳細介紹 HTML 媒…

輕量化分布式AGI架構:基于區塊鏈構建終端神經元節點的互聯網智腦

一、架構概述 該架構通過將終端設備(如手機、IoT設備)轉化為神經元節點,結合區塊鏈技術構建去中心化智能網絡,形成“互聯網智腦”。其核心在于突破傳統AGI算力瓶頸,實現數據安全共享與價值分配。 1.1 關鍵特征 分布…

【知識圖譜構建系列6】:借了張顯卡先跑著

文章目錄 前情提要mistral模型運行代碼前情提要 之前咱對LLM4KGC的代碼稍作修改,目標是用modelscope來下載模型。 現在這個代碼終于能跑了。 前面咱說,我們的顯卡只有6G的顯存。現在呢,我也成功借到了A100的顯卡。這下,咱可以先跑跑這個項目默認帶的mistral模型。 mist…

從零開始手寫redis(16)實現漸進式 rehash map

手寫 Redis 系列 java從零手寫實現redis(一)如何實現固定大小的緩存? java從零手寫實現redis(三)redis expire 過期原理 java從零手寫實現redis(三)內存數據如何重啟不丟失? jav…

List、Queue、Deque、Stack常用方法總結

Java 中幾個常見的線性數據結構的 方法總結與對比,包括: List(ArrayList、LinkedList)Queue(LinkedList、PriorityQueue)Deque(ArrayDeque、LinkedList)Stack(傳統 Stac…

github為InfiniSynapse Docker提PR過程留檔@Windows10

為InfiniSynapse Docker提了一個PR:修改阿里源為清華源,并不再安裝PPA。 by skywalk163 Pull Request #1 chaozwn/infini_docker 整體操作 提PR的前置動作 先fork要提PR的項目git clone到本地用VSCode修改代碼 提交PR git add . git commit -m &…

搭建加解密網站遇到的問題

本機向云服務器傳輸文件 用winscp 服務器在安裝 SSH 服務時自動生成密鑰對(公鑰私鑰) 為什么要有指紋驗證? 防止中間人攻擊(Man-in-the-Middle) 指紋驗證打破這個攻擊鏈: 小問題 安裝python時 ./confi…

Docker高級管理--容器通信技術與數據持久化

第一節:容器通信技術 一:Docker 容器的網絡模式 當項目大規模使用 Docker 時,容器通信的問題也就產生了。要解決容器通信問題,必須先了解很多關于網絡的知識。Docker 的網絡模式非常豐富,可以滿足不同容器的通信要求&…

jsons.top工具之數組交集、去重

作為一名程序員,一款高效的 在線轉換工具 (在線時間戳轉換 計算器 字節單位轉換 json格式化)必不可少!https://jsons.top 用js實現一個輕量級的集合運算工具,可以對數組、集合去重、求交并差集,找出兩個集…

Vue3 + Tailwind CSS 后臺管理系統教程

Vue3 搭配 Tailwind CSS 是構建現代后臺管理系統的絕佳組合。Vue3 提供了高效的響應式框架,而 Tailwind CSS 則讓樣式編寫變得快速且靈活。下面我將分步驟教你如何創建一個功能完整的后臺管理系統。 第 1 步:創建項目 首先,我們需要使用 Vit…

ComfyUI遭“Pickai“C++后門攻擊,全球700余臺AI圖像生成服務器淪陷

大規模AI基礎設施遭遇定向攻擊 網絡安全研究機構XLab近日發現針對ComfyUI框架的活躍攻擊活動。ComfyUI是當前廣泛用于部署大型AI圖像生成模型的開源框架。攻擊者通過該框架漏洞植入名為Pickai的C后門程序,已導致全球近700臺服務器失陷。中國國家網絡安全通報中心于…

Unity_VR_如何用鍵鼠模擬VR輸入_PICO項目配置

文章目錄 [TOC] 一、創建項目1.直接創建VR核心模板(簡單)2.創建3D核心模板導入XR包(并配置pico)(1)創建項目(2)導入PICO的SDK(3)啟用 PICO XR 插件&#xff0…

站點天下--網站在線和SSL過期監控的可靠助手

簡介 網站突然訪問不了、HTTPS證書到期,如果不能及時發現,將蒙受損失~ 站點天下提供應用在線狀態監控和SSL證書到期監控: 若訪問不了或SSL證書即將到期,則立即發郵件通知!可以在線查看應用的在線狀態和SSL證書到期時…

React setState原理

異步更新 原因 1設置為異步提升性能 如果setState每次調用直接執行,會造成 render 函數被頻繁執行 ,頁面重新被渲染 解決:異步批處理 2如果render函數未執行時,保證props和state一致性 拿到最新state的方法 法一:setState&…

漢代大模型:歷史鏡像與智能重構的深度對話

引言:當歷史遇見人工智能 一件漢代陶俑的三維模型正通過增強現實技術向觀眾演繹農耕場景。這個看似尋常的文物活化案例,實則蘊含著人工智能與歷史學交叉領域的前沿探索——漢代大模型。作為連接過去與未來的智能載體,漢代大模型不僅重構了我…

es向量檢索里的efSearchc參數是干嘛用的

在Elasticsearch的向量檢索中,ef_search(或efSearch)是控制HNSW近似最近鄰(ANN)搜索精度與性能平衡的關鍵參數,其作用機制和影響如下: 🛠? 一、核心作用 ef_search 限制底層圖遍歷…

Mac SSH終端操作工具 SecureCRT

SecureCRT Mac 是一款SSH終端工具,為計算專業人士提供高級會話管理工具。 也是一個功能強大且值得信賴的基于GUI的SHH和Telnet客戶端,以及旨在提高工作效率并簡化重復任務的終端仿真器。 借助SecureCRT mac版的幫助,您可以通過對ANSI&#…