Python實(shí)現(xiàn)單例模式的幾種方式

[TOC]

單例模式

單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式贞间,該模式的主要目的是確保某一個類只有一個實(shí)例存在挠唆。當(dāng)你希望在整個系統(tǒng)中处窥,某個類只能出現(xiàn)一個實(shí)例時,單例對象就能派上用場玄组。

比如滔驾,某個服務(wù)器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息俄讹。如果在程序運(yùn)行期間哆致,有很多地方都需要使用配置文件的內(nèi)容,也就是說患膛,很多地方都需要創(chuàng)建 AppConfig 對象的實(shí)例摊阀,這就導(dǎo)致系統(tǒng)中存在多個 AppConfig 的實(shí)例對象,而這樣會嚴(yán)重浪費(fèi)內(nèi)存資源,尤其是在配置文件內(nèi)容很多的情況下驹溃。事實(shí)上城丧,類似 AppConfig 這樣的類,我們希望在程序運(yùn)行期間只存在一個實(shí)例對象豌鹤。

在 Python 中亡哄,我們可以用多種方法來實(shí)現(xiàn)單例模式:

  • 使用模塊
  • 使用__new__
  • 使用裝飾器(decorator)
  • 使用元類(metaclass)

使用模塊

其實(shí),Python 的模塊就是天然的單例模式布疙,因?yàn)槟K在第一次導(dǎo)入時蚊惯,會生成 .pyc 文件,當(dāng)?shù)诙螌?dǎo)入時灵临,就會直接加載 .pyc 文件截型,而不會再次執(zhí)行模塊代碼。因此儒溉,我們只需把相關(guān)的函數(shù)和數(shù)據(jù)定義在一個模塊中宦焦,就可以獲得一個單例對象了。如果我們真的想要一個單例類顿涣,可以考慮這樣做:

# mysingleton.py
class My_Singleton(object):
    def foo(self):
        pass
 
my_singleton = My_Singleton()

將上面的代碼保存在文件 mysingleton.py 中波闹,然后這樣使用:

from mysingleton import my_singleton
my_singleton.foo()

裝飾器

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]

    return _singleton

@Singleton
class A(object):
    a = 1

    def __init__(self, x=0):
        self.x = x

a1 = A(2)
a2 = A(3)

基于__new__方法

#單例模式 在多線程下失效
class Singleton:
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

基于__new__方法加線程鎖

# 基于__new__然后加鎖
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

obj1 = Singleton()
obj2 = Singleton()
print(obj1,obj2)

基于metaclass

import threading

class SingletonType(type):
    _instance_lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        # print(args)
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name
        
#     def __new__(cls, *args, **kwargs):
#         print('Foo __init__')
#         return object.__new__(cls)


obj1 = Foo('name')
obj2 = Foo('name')
print(obj1,obj2)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涛碑,隨后出現(xiàn)的幾起案子精堕,更是在濱河造成了極大的恐慌,老刑警劉巖蒲障,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歹篓,死亡現(xiàn)場離奇詭異,居然都是意外死亡揉阎,警方通過查閱死者的電腦和手機(jī)庄撮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來余黎,“玉大人重窟,你說我怎么就攤上這事【宀疲” “怎么了巡扇?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長垮衷。 經(jīng)常有香客問我厅翔,道長,這世上最難降的妖魔是什么搀突? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任刀闷,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甸昏。我一直安慰自己顽分,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布施蜜。 她就那樣靜靜地躺著卒蘸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪翻默。 梳的紋絲不亂的頭發(fā)上缸沃,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機(jī)與錄音修械,去河邊找鬼趾牧。 笑死,一個胖子當(dāng)著我的面吹牛肯污,可吹牛的內(nèi)容都是我干的翘单。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼仇箱,長吁一口氣:“原來是場噩夢啊……” “哼县恕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剂桥,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎属提,沒想到半個月后权逗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冤议,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年斟薇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恕酸。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡堪滨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蕊温,到底是詐尸還是另有隱情袱箱,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布义矛,位于F島的核電站发笔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凉翻。R本人自食惡果不足惜了讨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧前计,春花似錦胞谭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至势就,卻和暖如春泉瞻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苞冯。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工袖牙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舅锄。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓鞭达,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皇忿。 傳聞我的和親對象是個殘疾皇子畴蹭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容