python 單例模式

使用模塊

其實,Python 的模塊就是天然的單例模式,因爲模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。

class TestSingleton(object):
    def test(self):
        pass
 
test = TestSingleton()

使用 __new__

爲了使類只能出現一個實例,我們可以使用 __new__ 來控制實例的創建過程

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
        return cls._instance

class Test(Singleton):
    test = 111

print(id(Test()))
print(id(Test()))
print(id(Test()))
print(id(Test()))

139639721336784
139639721336784
139639721336784
139639721336784

使用裝飾器

裝飾器(decorator)可以動態地修改一個類或函數的功能。這裏,我們也可以使用裝飾器來裝飾某個類,使其只能生成一個實例

from functools import wraps
 
def singleton(cls):
    instances = {}
    @wraps(cls)
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return getinstance
 
@singleton
class Test(object):
    a = 111

在上面,我們定義了一個裝飾器 singleton,它返回了一個內部函數 getinstance,該函數會判斷某個類是否在字典 instances 中,如果不存在,則會將 cls 作爲 key,cls(*args, **kw) 作爲 value 存到 instances 中,否則,直接返回 instances[cls]。

使用 metaclass

元類(metaclass)可以控制類的創建過程,它主要做三件事:

  • 攔截類的創建
  • 修改類的定義
  • 返回修改後的類
class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]
 
''' Python2 '''
class Test(object):
    __metaclass__ = Singleton
 
''' Python3 '''
# class Test(metaclass=Singleton):
#    pass

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章