Python設計模式——單例模式
阿新 • • 發佈:2018-02-07
ack 查看 繼承 一起 實現 不同的 ont 大神 使用方法 一、單例模式理論
單例模式:
保證某一個類只有一個實例,而且在全局只有一個訪問點
優點:
1、由於單例模式要求在全局內只有一個實例,因而可以節省比較多的內存空間
2、全局只有一個接入點,可以更好地進行數據同步控制,避免多重占用
3、單例可長駐內存,減少系統開銷
缺點:
1、單例模式的擴展是比較困難的
2、賦予了單例模式太多的職責,某種程度上違反了單一職責原則(六大設計原則之一)
3、單例模式是並發協作軟件模塊中需要最先完成的,因而其不利於測試
4、單例模式在某種情況下會導致資源瓶頸
應用場景:
1、生成全局唯一的變量,比如序列號
2、訪問全局復用的唯一資源,如磁盤,總線等3、單個對象占用的資源太多,如數據庫等
4、系統全局統一管理,如windows下的任務管理器
二、對__new__的分析
# class Demo: # def __init__(self, name): # self.name = name # # def show_name(self): # print("Name is: {}".format(self.name)) # # if __name__ == '__main__': # # d = Demo("toby") # d.show_name() ''' 引用大神的描述: 這樣便是__init__最普通的用法了。但__init__其實不是實例化一個類的時候第一個被調用的方法。 當使用Demo("toby")這樣的表達式來實例化一個類時,最先被調用的方法其實是 __new__ 方法。 __new__ 方法是什麽? __new__方法接受的參數雖然也是和__init__一樣,但__init__是在類實例創建之後調用,而__new__方法正是創建這個類實例的方法。 ''' class Demo: def __new__(cls, name): print("Call __new__") class_instance = super(Demo, cls).__new__(cls) print("new創建了類實例:", class_instance) #打印一下 return class_instance #返回Demon類的一個實例給__init__,然後利用這個實例來調用類的__init__方法 def __init__(self, name): #那__init__用什麽來接收__new__返回來的類實例呢?答案就是self print("init接收到new返回回來的類實例:", self) #打印一下這個self,也就是看一下由__new__產生的實例 print("Call __init__") self.name = name def show_name(self): print("Name is: {}".format(self.name)) # # if __name__ == '__main__': # d = Demo("toby") # d.show_name() ''' 引用大神的總結: 所以,__init__ 和 __new__ 最主要的區別在於: 1、__init__ 通常用於初始化一個新實例,控制這個初始化的過程,比如添加一些屬性, 做一些額外的操作,發生在類實例被創建完以後。它是實例級別的方法。 2、__new__ 通常用於控制生成一個新實例的過程。它是類級別的方法。 但是說了這麽多,__new__最通常的用法是什麽呢,我們什麽時候需要__new__?,單例模式就是一個很好的例子 '''
三、單例模式(案例1)
#coding:utf-8 import threading import time #這裏使用方法__new__來實現單例模式 class Singleton(object): #抽象單例 def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): orig = super(Singleton, cls) cls._instance = orig.__new__(cls, *args, **kwargs) return cls._instance #總線 class Bus(Singleton): lock = threading.RLock() def sendData(self, data): self.lock.acquire() time.sleep(3) print("Sending Signal Data...", data) self.lock.release() #線程對象,為更加說明單例的含義,這裏講Bus對象實例化在了run裏 class VisitEntity(threading.Thread): my_bus = "" name = "" def getName(self): return self.name def setName(self, name): self.name = name def run(self): self.my_bus = Bus() self.my_bus.sendData(self.name) if __name__ == '__main__': for i in range(3): print("Entity {} begin to run...".format(i)) v = VisitEntity() v.setName("Toby"+str(i)) v.start()
四、單例模式(案例2)
#使用__new__類方法來保證只有一個實例被創建出來 class OneOnly(object): _singleton = None def __new__(cls, *args, **kwargs): if not cls._singleton: #判斷是否創建有實例,如果沒有則調用super()函數來創建它 cls._singleton = super(OneOnly, cls).__new__(cls) #構造方法__new__被調用時,會構造該類的一個新實例 return cls._singleton #定義一個普通的類,僅有初始化方法__init__ class Test: def __init__(self, name): self.name = name #定義一個Demo類,並繼承實現單例模式的OneOnly類 class Demo(OneOnly): def __init__(self, name): self.name = name def chage_name(self, new_name): self.name = new_name def show_name(self): print("Name is: {}".format(self.name)) if __name__ == '__main__': #當通過OneOnly類中的構造方法構造實例時,總是會的得到完全相同的實例,內存地址也相同 # o1 = OneOnly() # o2 = OneOnly() # print(o1) # print(o2) #通過Test類創建出來的兩個實例t1和t2,是兩個不同的實例,內存地址也是不同的 # t1 = Test("toby") # t2 = Test("ttr") # print(t1) # print(t2) #Demo類繼承了實現了單例模式的OneOnly類,因此,通過Demo類實例化出來的對象都是同一個對象 d1 = Demo("toby") d2 = Demo("ttr") d3 = Demo("laowang") # 通過打印可知,他們的內存地址都是一樣的 # print(d1) # print(d2) #發現打印出來的name都是"laowang",似乎最後創建的一個實例把前兩個的給覆蓋了 d1.show_name() d2.show_name() d3.show_name() #通過實例d1修改名字後,再通過實例d3和d2來查看,果然也一起改變了。由此證明他們確實是同一個實例 d1.chage_name("juck") d3.show_name() d2.show_name()
Python設計模式——單例模式