成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

用Python實(shí)現(xiàn)設(shè)計(jì)模式——單例模式

CollinPeng / 1022人閱讀

摘要:前言單例模式是設(shè)計(jì)模式中最簡(jiǎn)單最容易理解的一種,維基百科的定義如下單例模式,也叫單子模式,是一種常用的軟件設(shè)計(jì)模式。

前言

單例模式是設(shè)計(jì)模式(Design Pattern)中最簡(jiǎn)單、最容易理解的一種,維基百科[1]的定義如下:

單例模式,也叫單子模式,是一種常用的軟件設(shè)計(jì)模式。在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類(lèi) "類(lèi) (計(jì)算機(jī)科學(xué))")必須保證只有一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)的全局對(duì)象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為。

單例模式的主要優(yōu)點(diǎn)是共享資源和減少資源消耗,主要應(yīng)用于IO或數(shù)據(jù)庫(kù)的線程池,緩存,日志,對(duì)話和需共享數(shù)據(jù)的資源等,但是在實(shí)現(xiàn)情況中濫用單例模式會(huì)帶來(lái)很多意想不到的問(wèn)題,本文重點(diǎn)在于介紹幾種Python實(shí)現(xiàn)單例模式的方法,這里就不再展開(kāi)論述了。文中所演示的代碼都會(huì)托管在Github上。

簡(jiǎn)單實(shí)現(xiàn)

首先,我們先嘗試用Python內(nèi)部類(lèi)(嵌套類(lèi))來(lái)實(shí)現(xiàn)單例模式:

#coding=utf-8
class Singleton:
    """單列類(lèi)
    """
    class __MyClass:
        """實(shí)際生成實(shí)例的類(lèi)
        """
        def __init__(self, arg):
            """初始化并賦值"""
            self.foo = arg

        def display(self):
            """返回實(shí)例的id和屬性值"""
            return (id(self), self.foo)

    # 類(lèi)屬性
    _instance = None
    def __init__(self, arg):
        if not Singleton._instance:
            Singleton._instance = Singleton.__MyClass(arg)
        else:
            Singleton._instance.foo = arg

    def __getattr__(self, attr):
        return getattr(self._instance, attr)

注意實(shí)際生成實(shí)例的類(lèi)是內(nèi)部的“__MyClass”類(lèi),前面的雙下劃線代表這是一個(gè)私有的類(lèi),用戶(hù)不能再外面直接訪問(wèn)它。而在"__MyClass"類(lèi)外封裝了一個(gè)“Singleton”類(lèi),這個(gè)類(lèi)的任務(wù)就是在初始化時(shí)保證整個(gè)上下文中只有一個(gè)實(shí)例,實(shí)現(xiàn)的方式很簡(jiǎn)單。用一個(gè)私有屬性__instance_保存當(dāng)前生成的實(shí)例,在初始化時(shí)判斷實(shí)例是否為_(kāi)None_,如果是就用“__MyClass”類(lèi)生成一個(gè)新實(shí)例并賦值給__instance_,否就直接返回或調(diào)用當(dāng)前__instance_的實(shí)例。最后用"__MyClass"里的實(shí)現(xiàn)的方法測(cè)試一下:

if __name__ == "__main__":
    """測(cè)試"""
    s1 = Singleton("bar")
    s2 = Singleton("zoo")
    print(s1.display())
    print(s2.display())

# output
>(41706760L, "zoo")
>(41706760L, "zoo")
基類(lèi)

現(xiàn)在我們考慮將inner class拆分出來(lái),因?yàn)樵赑ython類(lèi)實(shí)例化時(shí)會(huì)調(diào)用___new___方法[2]來(lái)生成實(shí)例,所以我們可以先繼承“Singleton”類(lèi),然后通過(guò)重寫(xiě)基類(lèi)的___new___方法讓其實(shí)現(xiàn)單例模式:

#coding=utf-8
class Singleton(object):
    """單例類(lèi)
    """
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

class MyClass(Singleton):
    """實(shí)際生成實(shí)例的類(lèi)
    """
    def __init__(self, arg):
        self.foo = arg

    def display(self):
        return (id(self), self.foo)

測(cè)試結(jié)果:

if __name__ == "__main__":
    s1 = MyClass("bar")
    s2 = MyClass("zoo")
    print(s1.display())
    print(s2.display())
    assert s1 is s2

# output
>(40882416L, "zoo")
>(40882416L, "zoo")
裝飾器

第三種就是最常見(jiàn)的用裝飾器來(lái)實(shí)現(xiàn)單列模式:

#coding=utf-8
def singleton(cls):
    instances = {}
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class MyClass:
    """實(shí)際生成實(shí)例的類(lèi)
    """
    foo = "foo"
    def display(self):
        return (id(self))

@singleton
class OtherClass:
    """另一個(gè)類(lèi)
    """
    pass

裝飾器的實(shí)現(xiàn)過(guò)程是將生成的實(shí)例都放到一個(gè)名為_(kāi)instances_的Dict中映射好,這樣每次在類(lèi)初始化時(shí)先檢查_(kāi)instances_中是否已經(jīng)包含有例化好的實(shí)例,有就直接返回是咧,沒(méi)有則調(diào)用類(lèi)初始化一個(gè)并賦值給_instances_列表。裝飾器的好處在于用一個(gè)Dict列表來(lái)管理所有需要實(shí)現(xiàn)單例模式的類(lèi),更簡(jiǎn)便和通用化。代碼的測(cè)試結(jié)果如下:

if __name__ == "__main__":
    s1 = MyClass()
    s1.foo = "bar"
    print(s1.display(), s1.foo)
    s2 = MyClass()
    s2.foo = "zoo"
    print(s2.display(), s2.foo)
    assert s1 is s2
    s3 = OtherClass()
    s4 = OtherClass()
    assert s3 is s4
元類(lèi)

如果希望不僅僅是通過(guò)限制而是在源頭上就創(chuàng)建一個(gè)單例類(lèi),我們需要用到元類(lèi)來(lái)實(shí)現(xiàn),元類(lèi)可以參考Stackoverflow[3]上的一個(gè)解答。簡(jiǎn)單的說(shuō)就是Python中的類(lèi)也是一種對(duì)象,被稱(chēng)為類(lèi)對(duì)象。類(lèi)對(duì)象可以通過(guò)元類(lèi)type來(lái)創(chuàng)建,而在此過(guò)程中會(huì)調(diào)用type__call__ 方法。所以我們只要在type創(chuàng)建類(lèi)對(duì)象的過(guò)程中重寫(xiě) __call__ 方法,在其中加入相應(yīng)的創(chuàng)建單例的邏輯即可實(shí)現(xiàn)單例模式,具體代碼實(shí)現(xiàn)如下:

#coding=utf-8
class Singleton(type):
    def __call__(cls, *args, **kwargs):
        """重寫(xiě),實(shí)現(xiàn)單例模式"""
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance

class MyClass(object):
    # 指定元類(lèi)
    __metaclass__ = Singleton

    def display(self):
        return (id(self))

代碼的測(cè)試與前面類(lèi)似,這里就不再累述了。

線程安全

最后,需要注意的是單例模式在多線程下可能會(huì)出現(xiàn)線程安全的問(wèn)題,這時(shí)候就需要在單例的初始化過(guò)程中加上線程同步鎖來(lái)避免,但這樣又會(huì)降低整體的性能,具體可以參考這篇文檔。

參考

[1]維基百科
[2]Python官方文檔
[3]Stackoverflow

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/41304.html

相關(guān)文章

  • Python單例模式(Singleton)的N種實(shí)現(xiàn)

    摘要:本篇文章總結(jié)了目前主流的實(shí)現(xiàn)單例模式的方法供讀者參考。使用實(shí)現(xiàn)單例模式同樣,我們?cè)陬?lèi)的創(chuàng)建時(shí)進(jìn)行干預(yù),從而達(dá)到實(shí)現(xiàn)單例的目的。 很多初學(xué)者喜歡用 全局變量 ,因?yàn)檫@比函數(shù)的參數(shù)傳來(lái)傳去更容易讓人理解。確實(shí)在很多場(chǎng)景下用全局變量很方便。不過(guò)如果代碼規(guī)模增大,并且有多個(gè)文件的時(shí)候,全局變量就會(huì)變得比較混亂。你可能不知道在哪個(gè)文件中定義了相同類(lèi)型甚至重名的全局變量,也不知道這個(gè)變量在程序的某...

    Maxiye 評(píng)論0 收藏0
  • Python new 類(lèi)方法和 init 實(shí)例方法以及單例模式的簡(jiǎn)單討論

    摘要:中的類(lèi)都是單例模式一天,一同事問(wèn)我這樣一個(gè)問(wèn)題。與方法屬于新式類(lèi),即屬于類(lèi)。方法在實(shí)例被創(chuàng)建之后被調(diào)用,該方法僅僅是對(duì)方法創(chuàng)建的實(shí)例進(jìn)行一些初始化操作。需要注意的是,在重寫(xiě)方法與方法的參數(shù)應(yīng)該保持一致,否則會(huì)有發(fā)生。 Python 中的類(lèi)都是單例模式? 一天,一同事問(wèn)我這樣一個(gè)問(wèn)題。這是一個(gè)奇怪的問(wèn)題,可能你也這么認(rèn)為。這里先不做解釋?zhuān)覀兿葋?lái)看看 __new__ 和 __init__...

    FingerLiu 評(píng)論0 收藏0
  • Python 中的單例模式

    摘要:在中,我們可以用多種方法來(lái)實(shí)現(xiàn)單例模式使用模塊使用使用裝飾器使用元類(lèi)使用模塊其實(shí),的模塊就是天然的單例模式,因?yàn)槟K在第一次導(dǎo)入時(shí),會(huì)生成文件,當(dāng)?shù)诙螌?dǎo)入時(shí),就會(huì)直接加載文件,而不會(huì)再次執(zhí)行模塊代碼。 單例模式 單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式,該模式的主要目的是確保某一個(gè)類(lèi)只有一個(gè)實(shí)例存在。當(dāng)你希望在整個(gè)系統(tǒng)中,某個(gè)類(lèi)只能出現(xiàn)一個(gè)實(shí)例時(shí),單例對(duì)...

    khlbat 評(píng)論0 收藏0
  • python設(shè)計(jì)模式-單例模式

    摘要:實(shí)現(xiàn)實(shí)現(xiàn)單例模式有多種方案使用提供了非常易用的類(lèi),只要繼承它,就會(huì)成為單例。參考鏈接單例模式最后,感謝女朋友支持。 問(wèn)題:現(xiàn)代化的巧克力工廠具備計(jì)算機(jī)控制的巧克力鍋爐。鍋爐做的事情就是把巧克力和牛奶融在一起,然后送到下一個(gè)階段,以制成巧克力棒。下邊是一個(gè)巧克力公司鍋爐控制器的代碼,仔細(xì)觀察一下,這段代碼有什么問(wèn)題? class ChocolateBoiler(object): ...

    darkbug 評(píng)論0 收藏0
  • Python中的單例模式

    摘要:使用元類(lèi)可以控制類(lèi)的創(chuàng)建過(guò)程,它主要做三件事攔截類(lèi)的創(chuàng)建修改類(lèi)的定義返回修改后的類(lèi)使用元類(lèi)實(shí)現(xiàn)單例模式的代碼如下執(zhí)行結(jié)果 單例模式 單例模式(Singleton Pattern)是一種常用的軟件設(shè)計(jì)模式,該模式的主要目的是確保某一個(gè)類(lèi)只有一個(gè)實(shí)例存在。當(dāng)你希望在整個(gè)系統(tǒng)中,某個(gè)類(lèi)只能出現(xiàn)一個(gè)實(shí)例時(shí),單例對(duì)象就能派上用場(chǎng)。 比如,某個(gè)服務(wù)器程序的配置信息存放在一個(gè)文件中,客戶(hù)端通過(guò)一個(gè) ...

    church 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

CollinPeng

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<