# 前言 本系列的第五篇 這次是單例模式(Singleton) # 單例模式 一種創建型設計模式,它確保一個類別在整個應用程序中只能有一個實體,並提供一個全局訪問點來存取該實體。 適合用在需要確保系統中某個類別只能存在一個實體的場景,例如: * 日誌管理:應用程式中的日誌工具通常應該是單一的,讓整個系統都能共享同一個日誌實體。 * 配置管理:一個應用程式的配置通常只應該被建立一次,所有的模組共享相同的配置實體。 * 連接池(connect pool):在資料庫或資源連接池中,單例模式可以確保連接池被全域共享,避免重複建立。 ```python= from typing_extensions import Self class Singleton(): _instance = None def __new__(cls) -> Self: if cls._instance == None: cls._instance = super().__new__(cls) return cls._instance if __name__ == "__main__": s1 = Singleton() print(id(s1)) s2 = Singleton() print(id(s2)) print(s1 is s2) ``` 這裡使用`id()`來檢查記憶體位址 並且用`is`去判斷是否為相同的物件 得到的輸出為 ``` 2769516866944 2769516866944 True ``` 然而這個是比較經典的版本 在`Python`中,單例模式也能透過裝飾器`decorator`來實作 可以將需要的類別改成單例模式而不需要改變原先的原始碼 ```python= # Decorator version def singleton(cls): instances = {} # 透過字典儲存 def get_instance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) # 創建實例並存儲 return instances[cls] return get_instance @singleton class SingletonClass: def __init__(self, value): self.value = value if __name__ == "__main__": s1 = SingletonClass(10) s2 = SingletonClass(20) print(s1 is s2) print(s1.value) print(s2.value) ``` 輸出的結果為 ``` True 10 10 ``` 運作邏輯大致如下 當程式執行到`s1 = SingletonClass(10)`的時候 此時裝飾器檢查時發現尚未建立實例 執行`__init__`這個`method`,將10寫入 而執行到`s2 = SingletonClass(20)`時 裝飾器發現已經建立該實例 就不再執行`__init__`,而是直接回傳之前建立過的實例 故`s1.value`跟`s2.value`都是10 # 心得 概念很簡單,實務上也很常見 但實作時花了點時間研究`__init__`跟`__new__`這兩個特殊method的差別 才順利寫出來
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up