建立型模式分爲如下幾種。python
以上 5 種建立型模式,除了工廠方法模式屬於類建立型模式,其餘的所有屬於對象建立型模式。數據庫
單例(Singleton)模式的定義:指一個類只有一個實例,且該類能自行建立這個實例的一種模式。設計模式
例如,Windows 中只能打開一個任務管理器,這樣能夠避免因打開多個任務管理器窗口而形成內存資源的浪費,或出現各個窗口顯示內容的不一致等錯誤。緩存
在計算機系統中,還有 Windows 的回收站、操做系統中的文件系統、多線程中的線程池、顯卡的驅動程序對象、打印機的後臺處理服務、應用程序的日誌對象、數據庫的鏈接池、網站的計數器、Web 應用的配置對象、應用程序中的對話框、系統中的緩存等經常被設計成單例。安全
單例模式有 3 個特色:網絡
單例模式是設計模式中最簡單的模式之一。一般,普通類的構造函數是公有的,外部類能夠經過「new 構造函數()」來生成多個實例。多線程
可是,若是將類的構造函數設爲私有的,外部類就沒法調用該構造函數,也就沒法生成多個實例。ide
這時該類自身必須定義一個靜態私有實例,並向外提供一個靜態的公有函數用於建立或獲取該靜態私有實例。函數
Singleton 模式一般有兩種實現形式。性能
該模式的特色是類加載時沒有生成單例,只有當第一次調用 get_instance 方法時纔去建立這個單例。
class LazySingleton(object): __instance = None def __init__(self): """ Virtually private constructor. """ pass @staticmethod def get_instance(): """ Static access method. """ if LazySingleton.__instance == None: LazySingleton.__instance = LazySingleton() return LazySingleton.__instance s1 = LazySingleton() s2 = LazySingleton() print(s1._LazySingleton__instance, s2._LazySingleton__instance, end='\n') # 未調用get_instance方法時未建立 print(s1.get_instance(), s2.get_instance(), end='\n') # 指向同一對象
None None <__main__.LazySingleton object at 0x0000020A56899FD0> <__main__.LazySingleton object at 0x0000020A56899FD0>
注意:若是編寫的是多線程程序,注意存在線程非安全的問題。若是保證線程安全,那麼每次訪問時都要同步,會影響性能,且消耗更多的資源,這是懶漢式單例的缺點。
該模式的特色是類一旦加載就建立一個單例,保證在調用 get_instance 方法以前單例已經存在了。
class HungrySingleton(object): __instance = None def __new__(cls, *args, **kwargs): if cls.__instance == None: cls.__instance = super(HungrySingleton, cls).__new__(cls) return cls.__instance @staticmethod def get_instance(): return HungrySingleton.__instance h1 = HungrySingleton() h2 = HungrySingleton() print(h1._HungrySingleton__instance, h2._HungrySingleton__instance, end='\n') # 未調用get_instance方法時已經建立 print(h1.get_instance(), h2.get_instance(), end='\n') # 與上面一致
<__main__.HungrySingleton object at 0x0000020A568A1048> <__main__.HungrySingleton object at 0x0000020A568A1048> <__main__.HungrySingleton object at 0x0000020A568A1048> <__main__.HungrySingleton object at 0x0000020A568A1048>
餓漢式單例在類建立的同時就已經建立好一個靜態的對象供系統使用,之後再也不改變,因此是線程安全的,能夠直接用於多線程而不會出現問題。
【例1】用懶漢式單例模式模擬產生美國當今總統對象。
分析:在每一屆任期內,美國的總統只有一人,因此本實例適合用單例模式實現,圖所示是用懶漢式單例實現的結構圖。
class President(object): __instance = None def __init__(self): print("產生一個新總統") @staticmethod def get_instance(): if President.__instance == None: President.__instance = President() else: print("已經有一個總統了") return President.__instance def get_name(self): print("特朗普是新總統") if __name__ == '__main__': p1 = President.get_instance() p1.get_name() p2 = President.get_instance() p2.get_name() if p1 == p2: print('他們是同一人') else: print('他們不是同一人')
產生一個新總統 特朗普是新總統 已經有一個總統了 特朗普是新總統 他們是同一人
前面分析了單例模式的結構與特色,如下是它一般適用的場景的特色。
單例模式可擴展爲有限的多例(Multitcm)模式,這種模式可生成有限個實例並保存在 ArmyList 中,客戶須要時可隨機獲取,其結構圖如圖所示。