Python 設計模式:Singleton, Factory 與 Observer (第 20 章)

站主自己的課程,請大家支持
揭秘站長的架站心法:如何利用 Hugo × AI 打造高質感個人品牌網站? 揭秘站長的架站心法:如何利用 Hugo × AI 打造高質感個人品牌網站?
  • Post by
  • Jan 03, 2024
post-thumb

設計模式 (Design Patterns) 是一套被反覆驗證過的、解決特定軟體設計問題的最佳實踐。雖然 Python 的動態特性讓我們常常可以用更簡單的語法 (如一級函數、模組) 來取代傳統的 OOP 設計模式,但理解這些模式依然對架構大型系統非常有幫助。

本章將介紹三種最常見的模式。

1. 單例模式 (Singleton Pattern)

目的:確保一個類別只有一個實例 (Instance),並提供一個全域存取點。例如:資料庫連線池、全域設定檔。

Pythonic 的實作方式

在 Python 中,其實模組 (Module) 本身就是天然的 Singleton!

# db_config.py
class Database:
    def __init__(self):
        print("Loading Database Config...")

db = Database() # 模組載入時只會執行一次

# main.py
# from db_config import db
# 這裡 import 到的 db 永遠是同一個物件

經典實作 (覆寫 __new__)

如果你堅持要用 Class 來實作:

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            # 只有第一次會建立物件
            cls._instance = super().__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()

print(s1 is s2)  # True (兩個變數指向同一個記憶體位址)

2. 工廠模式 (Factory Pattern)

目的:將物件的建立邏輯封裝起來,讓客戶端程式碼不需知道具體的類別名稱。我們在第 18 章看過的 @classmethod 就是一種簡單的工廠。

簡單工廠 (Simple Factory)

class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            raise ValueError("Unknown animal type")

# 客戶端只需要知道 Factory,不需要直接 import Dog 或 Cat
pet = AnimalFactory.create_animal("dog")
print(pet.speak())

這在需要根據設定檔動態決定建立什麼物件時非常有用。

3. 觀察者模式 (Observer Pattern)

目的:定義物件間的一對多依賴關係,當一個物件狀態改變時,所有依賴它的物件都會收到通知並自動更新。這在 UI 事件處理 (Event Handling) 非常常見。

class Subject:
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

class Observer:
    def update(self, message):
        raise NotImplementedError

class EmailAlert(Observer):
    def update(self, message):
        print(f"[Email] 收到通知: {message}")

class LogSystem(Observer):
    def update(self, message):
        print(f"[Log] 寫入日誌: {message}")

# 建立主題
news_publisher = Subject()

# 訂閱
news_publisher.attach(EmailAlert())
news_publisher.attach(LogSystem())

# 發送通知
news_publisher.notify("伺服器當機了!")

輸出:

[Email] 收到通知: 伺服器當機了!
[Log] 寫入日誌: 伺服器當機了!

這達成了 鬆耦合 (Loose Coupling)Subject 不需要知道具體是誰在訂閱,只負責發送通知。

4. 總結

設計模式是軟體工程師的共同語言。學習模式不是為了要把簡單的問題複雜化,而是為了在面對複雜需求時,腦中有現成的架構藍圖。

Batch 4 (OOP & Advanced Topics) 重點回顧:

  • Ch 16: 繼承與多型 (Inheritance, Polymorphism)
  • Ch 17: 魔術方法 (Magic Methods)
  • Ch 18: 類別工具 (@property, @classmethod)
  • Ch 19: 上下文管理器 (Context Managers)
  • Ch 20: 設計模式 (Singleton, Factory, Observer)

我們已經完成了 Python 教學 2/3 的路程!下一階段 Batch 5 將帶領大家進入 檔案處理、異常處理進階與虛擬環境 等實戰領域。


延伸閱讀

LATEST POST
TAG