1. 程式人生 > >Python:單例模式

Python:單例模式

轉載自

單例(Singleton)模式 也叫單態模式

概述:單例(Singleton)模式要求一個類有且僅有一個例項,並且提供了一個全域性的訪問點。這就提出了一個問題:如何繞過常規的構造器,提供一種機制來保證一個類只有一個例項?客戶程式在呼叫某一個類時,它是不會考慮這個類是否只能有一個例項等問題的,所以,這應該是類設計者的責任,而不是類使用者的責任。 從另一個角度來說,Singleton模式其實也是一種職責型模式。因為我們建立了一個物件,這個物件扮演了獨一無二的角色,在這個單獨的物件例項中,它集中了它所屬類的所有權力,同時它也肩負了行使這種權力的職責!

語言是共通的,想要用不同語言實現單例模式,首先要清楚什麼是單例模式,單例模式即一個類有且僅有一個例項

,並且提供一個訪問該例項的全域性訪問點。那麼通過python怎麼實現一個類只能有一個例項呢。

首先先建立一個類,比如宇宙只有一個地球

  1. class Earth:

  2. pass

  3. a = Earth()

  4. print(id(a))

  5. b = Earth()

  6. print(id(b))

執行結果如下:

通過列印例項的id可以發現,地球類預設建立了兩個例項。

那麼怎麼能夠讓類只建立一個例項,而後再建立的例項是返回上一次的物件的引用呢?

我們瞭解到,python中,一個類建立物件例項是通過呼叫父類object的 __new__(cls)方法來建立物件的

我們可以通過重寫 __new__(cls)方法去實現類只建立一個例項

程式碼如下:

  1. class Earth(object):

  2. __instance=None #定義一個類屬性做判斷

  3. def __new__(cls):

  4. if cls.__instance==None:

  5. #如果__instance為空證明是第一次建立例項

  6. #通過父類的__new__(cls)建立例項

  7. cls.__instance==object.__new__(cls)

  8. return cls.__instance

  9. else:

  10. #返回上一個物件的引用

  11. return cls.__instance

  12. a = Earth()

  13. print(id(a))

  14. b = Earth()

  15. print(id(b))

執行結果如下:

可以看出它們id相同,是同一個物件。

 適用場景: 1.需要生成唯一序列的環境

                       2.需要頻繁例項化然後銷燬的物件。

                       3.建立物件時耗時過多或者耗資源過多,但又經常用到的物件。 

                       4.方便資源相互通訊的環境


   優點:1.實現了對唯一例項訪問的可控

               2.對於一些需要頻繁建立和銷燬的物件來說可以提高系統的效能。

   缺點:1. 不適用於變化頻繁的物件
               2.濫用單例將帶來一些負面問題,如為了節省資源將資料庫連線池物件設計為的單例類,可能會導致共享連線池物件的程式過多而出現連線池溢位。

               3.如果例項化的物件長時間不被利用,系統會認為該物件是垃圾而被回收,這可能會導致物件狀態的丟失。

比如:回收站,我們在實際使用中並不存在需要同時開啟兩個回收站視窗的必要性。網站的計數器:

如果你存在多個計數器,每一個使用者的訪問都重新整理計數器的值,這樣的話你的實計數的值是難以同步的。但是如果採用單例模式實現就不會存在這樣的問題,而且還可以避免執行緒安全問題。同樣多執行緒的執行緒池的設計一般也是採用單例模式,這是由於執行緒池需要方便對池中的執行緒進行控制

  同樣,對於一些應用程式的日誌應用,或者web開發中讀取配置檔案都適合使用單例模式,如HttpApplication 就是單例的典型應用。