Python學習:19.Python設計模式-單例模式

来源:https://www.cnblogs.com/liudi2017/archive/2018/07/31/9393614.html
-Advertisement-
Play Games

一、單例模式存在的意義 在這裡的單例就是只有一個實例(這裡的實例就像在面向對象的時候,創建了一個對象也可以說創建了一個實例),只用一個實例進行程式設計,首先我們可以瞭解一下什麼時候不適合使用單例模式,比如我們需要使用類同時創建多個對象的時候,且每個對象中封裝了不同的數據的時候,就不能使用單例模式,就 ...


一、單例模式存在的意義

  在這裡的單例就是只有一個實例(這裡的實例就像在面向對象的時候,創建了一個對象也可以說創建了一個實例),只用一個實例進行程式設計,首先我們可以瞭解一下什麼時候不適合使用單例模式,比如我們需要使用類同時創建多個對象的時候,且每個對象中封裝了不同的數據的時候,就不能使用單例模式,就像下麵的例子

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
mingming = Person('明明',19)
mingyue = Person('明月',30)
mingri = Person('明日',20)

  那麼什麼時候適合使用單例模式,如果每個對象中封裝了相同的數據,但是需要創建多個對象的時候,而且這兩個實例所有的功能是一樣的,所以我們就可以使用一個實例完成,在這裡我們就可以使用單例模式,如下

class Person:
    def __init__(self):
        self.name = '123123'
        self.age = '20'

    def f1(self):
        pass

    def f2(self):
        pass

mingming = Person()
mingming.f1()

mingyue = Person()
mingyue.f1()

  為什麼要使用單例模式,就是為了在封裝數據相同的情況下,而且每個實例可執行的方法相同的時候,不必創建多個對象,只需要使用一個實例,來完成多個相同實例所完成的功能,通過這種方式減少記憶體的使用。

二、單例模式應用的場景

  • 需要頻繁的進行創建和銷毀的對象;
  • 創建對象時耗時過多或耗費資源過多,但又經常用到的對象;
  • 工具類對象;
  • 頻繁訪問資料庫或文件的對象。

三、單例模式的優點以及缺點

優點

系統記憶體中該類只存在一個對象,節省了系統資源,對於一些需要頻繁創建銷毀的對象,使用單例模式可以提高系統性能。

由於單例模式在記憶體中只有一個實例,減少了記憶體開銷。 
單例模式可以避免對資源的多重占用,例如一個寫文件時,由於只有一個實例存在記憶體中,避免對同一個資源文件的同時寫操作。 
單例模式可以再系統設置全局的訪問點,優化和共用資源訪問。 
其中使用到單例模式時,考慮較多的就是多線程的情況下如何防止被多線程同時創建等問題。

當這個類的對象在多個地方創建的時候,使得內部的方法多次調用,但是希望只要一個對象操作這個方法,或者不希望多個地方同時調用這個方法,需要保持這個方法的單一性質,就用單利模式

缺點

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

四、單例模式代碼編寫

接下來我們就模擬一個資料庫連接池來實現單例模式
首先我們介紹一下資料庫連接池
我們通過程式進行資料庫的操作的時候,每次都需要連接資料庫,但是連接資料庫需要消耗較多的時間,所以我們可以在我們主機的記憶體里維護一個資料庫連接池,在這個連接池中有若幹個已經連接資料庫的連接,我們想要連接資料庫的時候直接到連接池中取出一個連接即可,省去了連接的時間。

非單例模式

import random

class SqlConnectionPool:

    __instance = None

    def __init__(self):
        self.ip = "127.0.0.1"
        self.port = 3306
        self.pwd = '123456'
        self.username = 'alexsel'
        #去連接
        self.conn_list = [1,2,3,4,5,6,7,8,9,10]

    def get_connection(self):
        #獲取連接
        r = random.randrange(1,11)
        return r


#我們創建多個對象記憶體地址是一樣的,說明拿到的是同一個對象
obj = SqlConnectionPool()
print(obj)
obj1 = SqlConnectionPool()
print(obj1)
obj2 = SqlConnectionPool()
print(obj2)

輸出結果:
<__main__.SqlConnectionPool instance at 0x0000000002630788>
<__main__.SqlConnectionPool instance at 0x0000000002630888>
<__main__.SqlConnectionPool instance at 0x00000000026308C8>

非單例模式每次記憶體輸出的結果都不同,下麵是單例模式。

import random

class SqlConnectionPool:

    __instance = None

    def __init__(self):
        self.ip = "127.0.0.1"
        self.port = 3306
        self.pwd = '123456'
        self.username = 'alexsel'
        #去連接
        self.conn_list = [1,2,3,4,5,6,7,8,9,10]

    @staticmethod   #靜態方法是由類調用的
    def get_instance():
        if SqlConnectionPool.__instance:
            return SqlConnectionPool.__instance
        else:
            #創建一個對象,並將對象賦值給靜態欄位__instance
            SqlConnectionPool.__instance = SqlConnectionPool()
            return SqlConnectionPool.__instance

    #單例模式關鍵代碼解析
    #當第一次調用這個靜態方法的時候,判斷__instacne的值是None所以執行else,然後在else中創建一個對象賦給靜態欄位__instance,然後返回這個靜態欄位
    #第二次調用這個今靜態方法的時候,判斷__instance的值為真,所以直接返回這個靜態欄位,而這個靜態欄位中包含的是第一次創建的對象,所以在以後調用這個方法
    #就只會調用第一次創建的對象,這就是單例模式

    def get_connection(self):
        #獲取連接
        r = random.randrange(1,11)
        return r


#我們創建多個對象記憶體地址是一樣的,說明拿到的是同一個對象
obj = SqlConnectionPool.get_instance()
print(obj)
obj1 = SqlConnectionPool.get_instance()
print(obj1)
obj2 = SqlConnectionPool.get_instance()
print(obj2)


輸出結果:
<__main__.SqlConnectionPool instance at 0x000000000260C808>
<__main__.SqlConnectionPool instance at 0x000000000260C808>
<__main__.SqlConnectionPool instance at 0x000000000260C808>

 以上是基於類,使用靜態欄位和靜態方法實現的一個單例模式。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 分數的表示 1.如果分數為負,負號放到分子上 2.如果分數為0,分子為0,分母為1 3.分子分母沒有除1以為的公約數(化簡) 分數的化簡 分三步: 1.調整分子分母的負號 2.處理分數為0的情況 3.約分:分子分母絕對值的最大公約數。 ...
  • C++的註釋有兩種 1. 雙斜杠開始到本行結束 (//) 2. 斜杠星開始 星斜杠結束 (/*)(*/) 我們把上次的代碼加上一個比較詳細的註釋。 註釋的目的: 讓代碼閱讀者更清晰的理解編碼者的代碼意義。 註釋的一種錯誤用法 ,/* */的嵌套使用 大家看一下代碼著色就能發現,嵌套使用後的註釋對會出 ...
  • 題意 交互題。 有$k$個值域為$[1, n]$的數。 請在不超過$60$次詢問內找出其中的兩個數。 每次詢問形式為1 x y 交互庫會返回$|x - a| <= |y - b| ? "TAK" : "NIE"$ 其中$a, b$分別是使得$|x - a|,|y - b|$最小的且存在於序列中的數。 ...
  • 父類 子類 測試類 設計思想:用隨機文件流把文件正向讀出並保存到了字元串中,將字元串倒序,顯示到控制台。 文件讀寫 目的 1 掌握文件讀寫的幾種方法 2 FileOutputStream和FileInputStream類的使用。 3 基本數據類型之間的轉換 實現文件讀取後轉換為大寫後寫入到目標文件中 ...
  • 創建實例: String str = new String();str = "String"; 1、char charAt(int index):返回指定索引位置的字元 2、String substring(int beginIndex):返回指定起始位置至字元串末尾的字元串 String subs ...
  • 前言 從文章的標題,就可以清晰地瞭解到,本文是來辨析三個容易將新手弄糊塗的技術名詞。如果,你一眼看過去就知道這三個名詞的區別及關係,那麼,這篇文章你可以不用繼續讀下去了;除非,你是想要看看我有什麼解釋的不對,來糾錯的(來找茬,哈哈),也歡迎留言。 名詞解釋 JPA(Java Persistence ...
  • 本文內容 OID查詢 對象導航查詢 HQL查詢 QBC查詢 SQL查詢 首發日期:2018-07-31 hibernate的查詢方式: hibernate有很多查詢方式 OID查詢 對象導航查詢: HQL查詢: QBC查詢: SQL查詢: OID查詢: OID查詢:基於唯一標識屬性(主鍵)來查詢 使... ...
  • 報錯信息部分截取: 錯誤根源: 排錯: 相信很多人都是這樣寫的init 文件的吧: 然後再叢manager啟動文件導入create_app 這樣寫了之後,那麼你就只能在視圖函數中執行資料庫操作了!!! 解決辦法: 方式一 直接實例化app 不要寫create_app函數了,在啟動文件中直接導入app ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...