Singleton
動機(Motivation)
- 在軟件系統(tǒng)中高每,經(jīng)常有這樣一些特殊的類攒砖,必須保證它們在系統(tǒng)中只存在一個實例夯膀,才能確保它們的邏輯正確性、以及良好的效率回俐。
- 如何繞過常規(guī)的構(gòu)造器逛腿,提供一種機制來保證一個類只有一個實例?
- 這應(yīng)該是類設(shè)計者的責任仅颇,而不是使用者的責任单默。
模式定義
保證一個類僅有一個實例,并提供一個該實例的全局訪問點忘瓦。
——《設(shè)計模式》GoF
要點總結(jié)
- Singleton模式中的實例構(gòu)造器可以設(shè)置為protected以允許子類派生搁廓。
- Singleton模式一般不要支持拷貝構(gòu)造函數(shù)和Clone接口,因為這有可能導(dǎo)致多個對象實例耕皮,與Singleton模式的初中違背境蜕。
- 如何實現(xiàn)多線程環(huán)境下安全的Singleton?注意對雙檢查鎖的正確實現(xiàn)凌停。
例子
方法1 使用模塊
其實,python的模塊就是天然的單例模式,因為模塊在第一次導(dǎo)入的時候,會生成.pyc文件,當?shù)诙螌?dǎo)入的時候,就會直接加載.pyc文件,而不是再次執(zhí)行模塊代碼.如果我們把相關(guān)的函數(shù)和數(shù)據(jù)定義在一個模塊中,就可以獲得一個單例對象了.
新建一個python模塊叫singleton,然后創(chuàng)建以下python文件mysingleton.py
class _Singleton(object):
def foo(self):
pass
Singleton = _Singleton()
在另一個py文件中使用:
from singleton.mysingleton import Singleton
方法2 基于new方法實現(xiàn)的單例模式
知識點:
- 一個對象的實例化過程是先執(zhí)行類的new方法,如果我們沒有寫,默認會調(diào)用object的new方法,返回一個實例化對象,然后再調(diào)用init方法,對這個對象進行初始化,我們可以根據(jù)這個實現(xiàn)單例.
- 在一個類的new方法中先判斷是不是存在實例,如果存在實例,就直接返回,如果不存在實例就創(chuàng)建.
# -*- coding:utf-8 -*-
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._instance_lock:
if not hasattr(Singleton, "_instance"):
Singleton._instance = object.__new__(cls)
return Singleton._instance
def task(arg):
obj = Singleton()
print(obj)
if __name__ == '__main__':
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
輸出
<__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710><__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710><__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710>
<__main__.Singleton object at 0x108a42710>