摘要:最近在學習設計模式而開發的語言中比較中意的就是了在這里總結下設計模式一般分為三大類構造型結構型行為型先從創建型設計模式開始創建型設計模式包括單例模式抽象工廠模式工廠方法模式生成器模式惰性初始化模式對象池模式原型模式單例模式單例模式的定義是保
最近在學習設計模式,而開發的語言中比較中意的就是python了,在這里總結下.
設計模式一般分為三大類:構造型,結構型,行為型
先從創建型設計模式開始,創建型設計模式包括:單例模式,抽象工廠模式,工廠方法模式,生成器模式,惰性初始化模式,對象池模式,原型模式.
單例模式單例模式的定義是:保證一個類僅有一個實例,并提供一個它的全局訪問點.
先來看看14年前(沒寫錯)的前輩介紹的單例模式例程
from __future__ import print_function class Borg: __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state self.state = "Init" def __str__(self): return self.state class YourBorg(Borg): pass if __name__ == "__main__": rm1 = Borg() rm2 = Borg() rm1.state = "Idle" rm2.state = "Running" print("rm1:{0}".format(rm1)) print("rm2:{0}".format(rm2)) rm2.state = "Zombie" print("rm1:{0}".format(rm1)) print("rm2:{0}".format(rm2)) print("rm1 id:{0}".format(id(rm1))) print("rm2 id:{0}".format(id(rm2))) rm3 = YourBorg() print("rm1:{0}".format(rm1)) print("rm2:{0}".format(rm2)) print("rm3:{0}".format(rm3)) # Output # rm1:Running # rm2:Running # rm1:Zombie # rm2:Zombie # rm1 id:140609170593696 # rm2 id:140609170593624 # rm1:Init # rm2:Init # rm3:Init
簡單解釋下,需要get的點是下面這段代碼
__shared_state = {} def __init__(self): self.__dict__ = self.__shared_state self.state = "Init"
self.__dict__是對象的字典表示.將對象的屬性設為全局靜態變量.
根據輸出結果,rm1和rm2儼然是一個實例.然而打印出來的rm1,rm2的變量id是不一致的,所以rm1,rm2并不是同一個實例.但是卻有同樣的狀態和行為.但從結果上來看,確實實現了單例模式的要求.(雖然有種走捷徑的感覺)
下面看看另一個版本的,其實就是換個形式,原理還是建多個實例,表現一致.其他部分的代碼和上面的一致.
class Borg(object): __state = {} def __new__(cls, *p, **k): self = object.__new__(cls, *p, **k) self.__dict__ = cls.__state return self def __init__(self): self.state = "Init"
單例模式的創建有很多種方式.
這里有討論鏈接描述
升級版,通過__metaclass__實現.這個版本中同一個id說明是同一個對象.
class Singleton(type): def __init__(self, name, bases, dict): super(Singleton, self).__init__(name, bases, dict) self._instance = None def __call__(self, *args, **kw): if self._instance is None: self._instance = super(Singleton, self).__call__(*args, **kw) return self._instance class MyClass(object): __metaclass__ = Singleton one = MyClass() two = MyClass() two.a = 3 print one.a # 3 print id(one) # 139798461922256 print id(two) # 139798461922256 print one == two # True print one is two # True
還可以通過裝飾器來實現.這是第一個方法的高級版本,更pythonic,更elegant的方法.
這個例子中,單例類本身不知道自己是單例的,應為他本身(自己的代碼)就不是單例的.
def singleton(cls, *args, **kw): instances = {} def _singleton(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return _singleton @singleton class MyClass(object): a = 1 def __init__(self, x=0): self.x = x one = MyClass() two = MyClass() two.a = 3 print one.a # 3 print id(one) # 140630714076048 print id(two) # 140630714076048 print one == two # True print one is two # True one.x = 1 print one.x # 1 print two.x # 1
好東西留到最后,來個超級無敵版的
class Singleton: """ A non-thread-safe helper class to ease Implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be singleton. The decorated class can define one `__init__` function that takes onelythe `self` argument. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instances, use the `instances` method. Trying to use `__call__` will result in a `TypeError` being raised. Limitations: The decorated class cannot be inherited from. """ def __init__(self, decorated): self._decorated = decorated def instance(self): """ Return the singleton instance. Upon this first call, it creates a new instance of decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance def __call__(self): raise TypeError("Singletons must be accessed through `instance()`.") def __instancecheck(self, inst): return isinstance(inst, self._decorated) @Singleton class Foo: def __init__(self): print "Foo created" # f = Foo() # TypeError: Singletons must be accessed through `instance()`. f = Foo.instance() g = Foo.instance() # Foo created print f is g # True
關于python的單例模式,各家說法不一.可以根據不同的需求,使用不同的方式,適合的才是最好的.
參考文字:
https://zh.wikipedia.org/wiki/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F_(%E8%AE%A1%E7%AE%97%E6%9C%BA)
http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/
http://code.activestate.com/recipes/66531/
http://blog.csdn.net/ghostfromheaven/article/details/7671853
http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python/31887#31887
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37691.html
摘要:當然,除了讓我們顯得更加專業之外,在自己所學習或者工作的項目中,適當合理的使用設計模式,能夠給項目帶來很大的好處。 簡單說兩句 本文首發公眾號【一名打字員】 對不住各位老鐵了,年前說好要更幾波JAVA的東西,又偷懶了,沒辦法,在這里用小錘錘偷偷錘了自己幾下。由于工作原因,更新時間不定,各位老鐵有問題可以私聊我哈。 對于初學者或者是正在向中高級的Java程序猿(打字員)來說,時刻梳理自己...
摘要:天入門三門編程語言,有可能嘛,尤其是對沒有基礎的同學來說對于想學好的編程的人來說,無論從哪一門語言開始入手,語言的本身其實并不是我們最應該的關心的,至少不是作為一個初學者首先關心的。 7天入門三門編程語言,有可能嘛,尤其是對沒有基礎的同學來說?對于想學好的編程的人來說,無論從哪一門語言開始入手,語言的本身其實并不是我們最應該的關心的,至少不是作為一個初學者首先關心的。 網絡上,網友們爭...
摘要:天入門三門編程語言,有可能嘛,尤其是對沒有基礎的同學來說對于想學好的編程的人來說,無論從哪一門語言開始入手,語言的本身其實并不是我們最應該的關心的,至少不是作為一個初學者首先關心的。 7天入門三門編程語言,有可能嘛,尤其是對沒有基礎的同學來說?對于想學好的編程的人來說,無論從哪一門語言開始入手,語言的本身其實并不是我們最應該的關心的,至少不是作為一個初學者首先關心的。 網絡上,網友們爭...
閱讀 1393·2021-11-22 15:11
閱讀 2838·2019-08-30 14:16
閱讀 2755·2019-08-29 15:21
閱讀 2914·2019-08-29 15:11
閱讀 2451·2019-08-29 13:19
閱讀 2985·2019-08-29 12:25
閱讀 417·2019-08-29 12:21
閱讀 2829·2019-08-29 11:03