單例模式是一種寫程序的方式,用單例模式設計的類,不管你去實例化多少次,獲得的都是同一個實例,通常咱們設計的類每次實例化都會生成不一樣的實例,可是單例模式就是反其道而行之,就像下面這樣:
上圖中的ClassA和ClassB 都是採用的 單例設計模式,而ClassC沒有采用單例設計模式咱們能夠清晰的看到 ClassA的兩個不一樣的實例在內存中的地址是相同的,也就是說兩次實例化獲得的對象是同一個對象,ClassB和ClassA也是同樣的,由於都採用了單例設計模式, 而ClassC由於沒有采用單例設計模式因此他的兩個實例對象指向不一樣的內存地址,也就是說兩次實例化獲得的是兩個不一樣的對象.編程
要弄清楚爲何須要單例模式, 首先須要知道單例模式提供了哪些優秀的特性?設計模式
單例模式提供的最爲優秀的特性就是:單例模式能夠容許你在程序的任何地方訪問某個特定的對象經過單例設計模式, 你能夠在不定義全局變量的狀況下,在程序的任何地方訪問你所指定的對象,單例模式所提供的功能和全局變量是同樣的, 可是經過單例模式設計, 你就能夠在無需犧牲代碼可讀性和安全性的前提下完成和全局變量徹底同樣的功能. 單例模式吸取了全局變量的優勢摒棄了全局變量的缺點,是替代可惡全局變量不二的選擇.安全
在上面的例子中咱們能夠看到不管實例化多少次ClassA獲得的都是同一個對象, 若是這個類處於一個比較大的工程中,在這個工程中的任何位置實例化ClassA獲得的都是同一個對象,這不就是全局變量嗎, 可是和全局變量不一樣的是經過單例模式產生對象的代碼更加的易讀,並且這種面向對象的編程方式能夠確保ClassA所產生的對象只能被對象自身的方法所操做, 這樣就更加的安全, 並且你能夠經過獲取實例的方法對返回對象的行爲進行更多的限制.爲何須要單例模式? 本質上是由於人們須要全局變量,須要一個更加好用更加安全的全局變量, 單例模式的出現解決了全局變量的現有問題, 因此人們才須要單例模式微信
單例模式像極了全局變量, 可是單例模式畢竟不是實現全局變量, 除了上述所說的異同點以外, 經過單例模式產生的對象和全局變量還有一個明顯的區別就是全局變量一旦定義就絕對不會再發生改變, 可是單例模式雖說每次返回的都是一個固定的對象, 但這個固定的對象仍是能夠經過單例類自身的一些方法去更改的,因此單例模式產生的對象和全局變量比起來只能說是相對固定的.
任何一門語言要想實現單例模式,可能都有不少的實現方法,可是實現思路大同小異,確定都是在第一次生成實例的時候就直接把實例給存儲到某個地方,而後在下一次實例化的時候直接返回這個事先被存儲起來的實例,而不是從新去實例化返回一個新的實例.
Python實現單例模式一個比較優雅的實現方式就是經過裝飾器去實現,以下所示:
def singleton(cls): instances = {} def getinstance(*args,**kwargs): if cls not in instances: instances[cls] = cls(*args,**kwargs) return instances[cls] return getinstance @singleton class ClassA: pass @singleton class ClassB: pass class ClassC: pass aa=ClassA() aaa=ClassA() bb=ClassB() bbb=ClassB() cc=ClassC() ccc=ClassC()
上面的例子咱們能夠看到singleton是一個裝飾器函數, 經過閉包的原理讓其內部的 instances 變量的生命週期和全局變量等同,而後把被裝飾的類第一次實例化生成的對象直接存儲在instances中,在取對象的時候直接從在instances字典中找到事先存儲好的對象返回,就是經過這樣的方式實現單例的.
單例模式的實現方式還有不少種: 好比經過類屬性實現, 經過元類實現等多種方式, 甚至每一種實現可能都有本身特定的應用場景, 可是我以爲經過裝飾器實現最爲優雅, 本着少就是多的原則, 其餘的實現方式我就再也不贅述, 若是對其餘的實現方式感興趣能夠在早睡蟒
公衆號後臺回覆跬蟒
加我微信(備註好公司崗位)交流溝通.
若是感受本篇內容還不錯,微信的朋友請點個在看和贊,其餘平臺的朋友能夠(近距離)掃描下方的二維碼關注個人公衆號 早睡蟒
更多優質原創無廣告內容等你來看.閉包