python單例模式


詳情參考:https://www.cnblogs.com/shenbuer/p/7724091.html

一、單例模式的概述:

單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱為單例類的特殊類。通過單例模式可以保證系統中一個類只有一個實例而且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。如果希望在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。

單例模式的要點有三個;一是某個類只能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。

從具體實現角度來說,就是以下三點:一是單例模式的類只提供私有的構造函數,二是類定義中含有一個該類的靜態私有對象,三是該類提供了一個靜態的共有函數用於創建或獲取它本身的靜態私有對象。

 

二、應用:

一些資源管理器常常設計成單例模式

在計算機系統中,需要管理的資源包括軟件外部資源,譬如每台計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印機作業同時輸出到打印機中。每台計算機可以有若干傳真機卡,但是只應該有一個軟件負責管理傳真卡,以避免一個通信端口同時被兩個請求同時調用。

需要管理的資源包括軟件內部資源,譬如,大多數的軟件都有一個(甚至多個)屬性(properties)文件存放系統配置。這樣的系統應當由一個對象來管理一個屬性文件。

需要管理的軟件內部資源也包括負責記錄網站來訪人數的部件,記錄軟件系統內部事件、出錯信息的部件,或是對系統的表現進行檢查的部件等。其一,這些資源管理器構件必須只有一個實例;其二,它們必須自行初始化;其三,允許整個系統訪問自己。因此,它們都滿足單例模式的條件,是單例模式的應用。

 

三、單例模式的優缺點:

優點:

1、實例控制

單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。

2、靈活性

因為類控制了實例化過程,所以類可以靈活更改實例化過程。

缺點:

1、開銷

雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。

2、可能的開發混淆

使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。

3、對象生成期

不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致單例類中出現懸浮引用。

 

四、在Python中,單例模式有以下幾種實現方式。

方法一、實現__new__方法,然后將類的一個實例綁定到類變量_instance上;如果cls._instance為None,則說明該類還沒有被實例化過,new一個該類的實例,並返回;如果cls._instance不為None,直接返回_instance,代碼如下:

復制代碼
class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            orig=super(Singleton,cls)
            cls._instance=orig.__new__(cls,*args,**kwargs)
        return cls._instance

class MyClass(Singleton):
    a=1

one=MyClass()
two=MyClass()

# one和two完全相同,可以用id(),==,is檢查
print(one.a)    # 1
print(id(one))  # 2565285375728
print(id(two))  # 2565285375728
print(one == two)   # True
print(one is two)   # True
復制代碼

方法二、本質上是方法一的升級版,使用metaclass(元類)的python高級用法,具體代碼如下

復制代碼
"""
class Singleton中的__init__在Myclass聲明的時候被執行Myclass=Singleton()
Myclass()執行時,最先執行父類的__call__方法(object,Singleton都作為Myclass的父類,
根據深度優先算法,會執行Singleton中的__call__(),Singleton中的__call__()寫了單例模式)
"""
class Singleton(type):

    def __init__(self, name, bases, dict):
        super(Singleton,self).__init__(name,bases, dict)
        self._instance = None

    def __call__(self, *args, **kwargs):
        if self._instance is None:
            self._instance = super(Singleton,self).__call__(*args, **kwargs)
        return self._instance

class MyClass(object,metaclass=Singleton):
    a = 1

one=MyClass()
two=MyClass()
print(id(one))  # 1553247294800
print(id(two))  # 1553247294800
print(one == two)   # True
print(one is two)   # True
復制代碼

 

方法三、使用python的裝飾器(decorator)實現單例模式,這是一種更Pythonic的方法;單例類本身的代碼不是單例的,通過裝飾器使其單例化,代碼如下:

復制代碼
def singleton(cls, *args, **kwargs):
    instances = {}
    
    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return _singleton

@singleton
class MyClass3(object):
    a = 1

one = MyClass3()
two = MyClass3()

print(id(one))  # 2880466769232
print(id(two))  # 2880466769232
print(one == two)   # True
print(one is two)   # True
復制代碼

python的單例模式__new__()在__init__()之前被調用,用於生產實例對象。利用這個方法和類的屬性的特點可以實現設計模式的單例模式。單例模式是指創建唯一對象,單例模式設計的類只能實例化一個對象。

復制代碼
class Singleton(object):
    __instance=None

    def __init__(self):
        pass
    def __new__(cls, *args, **kwargs):
        if Singleton.__instance is None:
            Singleton.__instance=object.__new__(cls,*args, **kwargs)
        return Singleton.__instance

one=Singleton()
two=Singleton()
print(id(one))  # 2488569943376
print(id(two))  # 2488569943376
print(one == two)   # True
print(one is two)   # True
復制代碼

單例模式是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱為單列類的特殊類。通過單列模式可以保證系統中一個類只有一個實例而且該實例易於外界訪問,從而便於對實例個數的控制並節約系統資源。如果希望在系統中某個類的對象只能存在一個,單例模式是最后的解決方案。

 

五、總結

內容:保證一個類只有一個實例,並提供一個訪問它的全局訪問點。
適用場景:當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時
優點:
    對唯一實例的受控訪問
    單例相當於全局變量,但防止了命名空間被污染
與單例模式功能相似的概念:全局變量、靜態變量(方法)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM