單例模式(singleton pattern)是一種常用的軟體設計模式,該模式的主要目的是確保某乙個類只有乙個例項存在。當你希望在整個系統中,某個類只能出現乙個例項時,單例物件就能派上用場。
單例模式的要點有三個;一是某個類只能有乙個例項;二是它必須自行建立這個例項;三是它必須自行向整個系統提供這個例項。
在 python 中,我們可以用多種方法來實現單例模式:
使用模組
使用new
使用裝飾器(decorator)
使用元類(metaclass)
1.使用模組
如果我們真的想要乙個單例類,可以考慮這樣做:
#tests1.py
class myclass(object):
def foo(self):
print(『myclass.foo』)
my_class_obj=myclass()
將上面的**儲存在檔案 tests1.py 中,然後這樣使用:
from .tests1 import my_class_obj
my_class_obj.foo()
這種方法相當於把乙個類寫成乙個例項化模組,無論你什麼時候呼叫,都是那乙個例項,所以就算乙個單列了
2.使用__new__函式
為了使類只能出現乙個例項,我們可以使用new來控制例項的建立過程,**如下:12
3456
789class myclass(object):
_instance = none
defnew(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(myclass, cls).new(cls, *args, **kwargs)
return cls._instance
class herclass(myclass):
a = 1
在上面的**中,我們將類的例項和乙個類變數 _instance 關聯起來,如果 cls._instance 為 none 則建立例項,否則直接返回 cls._instance。
執**況如下:=
one = herclass()
two = herclass()
print(one == two) #true
print(one is two) #true
print(id(one), id(two)) #42818864 42818864
3. 使用裝飾器
我們知道,裝飾器(decorator)可以動態地修改乙個類或函式的功能。這裡,我們也可以使用裝飾器來裝飾某個類,使其只能生成乙個例項,**如下:
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class myclass(object):
a = 1
在上面,我們定義了乙個裝飾器 singleton,它返回了乙個內部函式 getinstance,該函式會判斷某個類是否在字典 instances 中,如果不存在,則會將 cls 作為 key,cls(*args, **kw) 作為 value 存到 instances 中,否則,直接返回 instances[cls]。
4. 使用 metaclass
元類(metaclass)可以控制類的建立過程,它主要做三件事:
1.攔截類的建立
2.修改類的定義
3.返回修改後的類
使用元類實現單例模式的**如下:
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]
class myclass(metaclass=singleton):
pass
優點:
一、例項控制
單例模式會阻止其他物件例項化其自己的單例物件的副本,從而確保所有物件都訪問唯一例項。
二、靈活性
因為類控制了例項化過程,所以類可以靈活更改例項化過程。
缺點:
一、開銷
雖然數量很少,但如果每次物件請求引用時都要檢查是否存在類的例項,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。
二、可能的開發混淆
使用單例物件(尤其在類庫中定義的物件)時,開發人員必須記住自己不能使用 new關鍵字例項化物件。因為可能無法訪問庫源**,因此應用程式開發人員可能會意外發現自己無法直接例項化此類。
三、物件生存期
不能解決刪除單個物件的問題。在提供記憶體管理的語言中(例如基於.net framework的語言),只有單例類能夠導致例項被取消分配,因為它包含對該例項的私有引用。在某些語言中(如 c++),其他類可以刪除物件例項,但這樣會導致單例類**現懸浮引用。
類也是物件
只要你使用關鍵字class,python直譯器在執行的時候就會建立乙個物件。
下面的**段:
class myclass(object):
pass
print(myclass) # 你可以列印乙個類,因為它其實也是乙個物件
#def echo(o):
print(o)
echo(myclass) # 你可以將類做為引數傳給函式
myclass.new_attribute = 『foo』 # 你可以為類增加屬性
print(hasattr(myclass,『new_attribute』)) #true
print(myclass.new_attribute) #foo
myclassmirror=myclass # 你可以將類賦值給乙個變數
print(myclassmirror())
<main.myclass object at 0x00000000028cde10>
動態地建立類
因為類也是物件,你可以在執行時動態的建立它們,就像其他任何物件一樣。首先,你可以在函式中建立類,使用class關鍵字即可
def choose_class(name):
if name == 『foo』:
class foo(object):
pass
return foo # 返回的是類,不是類的例項
else:
class bar(object):
pass
return bar
myclass = choose_class(『foo』)
print(myclass) # 函式返回的是類,不是類的例項
print(myclass()) # 你可以通過這個類建立類例項,也就是物件
<main.choose_class..foo object at 0x00000000021e5cf8>
但這還不夠動態。
由於類也是物件,所以它們必須是通過什麼東西來生成的才對。
還記得內建函式type嗎?這個古老但強大的函式能夠讓你知道乙個物件的型別是什麼,就像這樣:
print(type(1)) #
print(type(『1』)) #
print(type(myclass)) #
print(type(myclass())) #
python單列模式 Python單列模式
實現單例模式的幾種方式 1.使用模組 2.使用裝飾器 3.使用類 4.基於 new 方法實現 推薦使用,方便 5.基於metaclass方式實現 單例模式 singleton pattern 是一種常用的軟體設計模式,該模式的主要目的是確保某乙個類只有乙個例項存在。當你希望在整個系統中,某個類只能出...
Python 物件導向 單列模式
1 什麼是單例模式 乙個類有且只能建立乙個物件空間,目的是為了節約記憶體資源 例如 站 資料庫操作類 只需要乙個物件就能完成所有的功能,沒有必要建立多個物件浪費記憶體資源.2.實現單例模式 class singleton object 類屬性 instance none isinit false 是...
Python 裝飾器實現單列模式
使用裝飾器實現單列模式 defsingleton cls 用來存在例項的字典 singleton instance 判斷字典中是否例項 ifnot singleton instance.get cls.name 沒有則建立乙個例項,並存入字典中 singleton instance cls.name...