nabroux's Obsidian vault, published.

Astro Techbook

語言
中文

Factory Method Pattern

my-notes/low-level-design-lld/design-patterns/creational-patterns · ZH

translationKey: factory-method-pattern #low level design #design pattern #creational pattern

類型:Creational Pattern 別名:Virtual Constructor(虛擬建構子)

💡 1. 定義(Definition)

Factory Method Pattern 定義一個建立物件的介面, 但讓子類別決定實際要建立哪一個類別。

✅ 換句話說:「把 new 的決定權延後到子類別。」

它解決的問題是:

當一個類別無法預先知道要建立哪一種具體物件時, 將物件建立的責任交給子類別或外部工廠。

🎯 2. 問題背景(Problem Statement)

假設你要設計一個文件轉換系統:

PDFConverter
WordConverter
ExcelConverter

如果你在主程式裡直接:

if file_type == "pdf":
    return PDFConverter()
elif file_type == "word":
    return WordConverter()

🔻 問題是:

  • 每增加一個新格式都得改程式碼(違反 開放封閉原則 OCP)。
  • 主程式與具體類別強耦合。

👉 解法: 將物件建立的邏輯封裝在「工廠方法」中。

⚙️ 3. 解決方案(Solution)

定義一個抽象的「Creator」類別, 其中包含一個抽象方法 create_product(), 子類別負責實際建立不同的產品(Product)。

🧱 4. 結構與角色(Structure & Participants)

角色 職責
Product (產品介面) 定義所有產品的共同介面
ConcreteProduct (具體產品) 各種具體實作類別
Creator (工廠介面) 定義抽象工廠方法 create_product()
ConcreteCreator (具體工廠) 實作工廠方法,建立對應產品
classDiagram class Creator { +create_product() Product +operation() } class ConcreteCreatorA { +create_product() ProductA } class Product { <<interface>> +use() } class ConcreteProductA { +use() } Creator <|-- ConcreteCreatorA Product <|-- ConcreteProductA Creator --> Product

🧩 5. 程式碼範例(Python)

from abc import ABC, abstractmethod

# === Product ===
class Document(ABC):
    @abstractmethod
    def open(self):
        pass

class PDFDocument(Document):
    def open(self):
        return "Opening PDF file..."

class WordDocument(Document):
    def open(self):
        return "Opening Word file..."


# === Creator ===
class DocumentCreator(ABC):
    @abstractmethod
    def create_document(self) -> Document:
        pass

    def open_file(self):
        doc = self.create_document()
        return doc.open()

class PDFCreator(DocumentCreator):
    def create_document(self):
        return PDFDocument()

class WordCreator(DocumentCreator):
    def create_document(self):
        return WordDocument()


# === 使用 ===
def client_code(creator: DocumentCreator):
    print("Client: I'm not aware of the creator's class, but it still works.")
    print(creator.open_file())

client_code(PDFCreator())
client_code(WordCreator())

🧠 說明:

  • DocumentCreator 是抽象工廠。
  • PDFCreator、WordCreator 負責實際建立具體文件。
  • Client 端完全不知道具體類別,達到鬆耦合

🧠 6. 實際應用場景(Real-world Use Cases)

場景 實例
🧩 檔案格式建立器 PDF / Excel / CSV parser
🧱 資料庫連線工廠 建立 MySQL / PostgreSQL client
🧠 AI 模型工廠 根據模型名稱建立不同推理 client(OpenAI / Anthropic)
🧾 Logger 工廠 根據環境建立不同 Logger(ConsoleLogger / FileLogger)
☁️ 雲端 SDK AWS / GCP 物件建立統一介面

⚖️ 7. 優點與缺點(Pros & Cons)

優點 缺點
✅ 將物件建立與使用分離 ❌ 類別數量會爆炸(每種產品要一個 Creator)
✅ 開放封閉原則(OCP) ❌ 較難追蹤實際建立的產品類別
✅ 易於測試與替換實作 ❌ 程式結構略顯冗長

🔍 8. 與其他模式比較(Comparison)

模式 差異
Simple Factory 非正式模式,由單一函式集中建立物件(不具擴展性)
Abstract Factory 同時建立一組相關物件(而非單一類別)
Builder 專注在「複雜物件的組裝過程」,不是選哪個類別

🧭 9. 實務設計指引(Design Tips)

  • ✅ 當「類別建立邏輯」開始變複雜時,優先考慮使用 Factory。
  • ✅ 若產品家族(Product Family)會擴展,用 Factory Method 取代 if-else。
  • 🚫 若僅有少數類別,不必為簡單場景過度設計。
  • 💬 可與 Dependency Injection 框架(如 FastAPI Depends)搭配使用。

🧮 10. 面試考點(Interview Insights)

問題 關鍵回答重點
Factory Pattern 解決什麼問題? 解耦物件建立與使用邏輯。
Factory 與 Abstract Factory 差別? 一對一 vs 一對多。
Python 中如何實現? 透過抽象類別 + 覆寫工廠方法。
現實中例子? SQLAlchemy engine 建立器、Django ORM connection backend。

✅ 11. 一句話總結(One-liner Summary)

「Factory Method Pattern 讓物件建立更彈性, 讓子類別決定要實際產生哪一種產品,達到擴展與解耦。」

📚 12. 延伸閱讀(Further Reading)

  • 📘 Design Patterns: Elements of Reusable Object-Oriented Software
  • 🧩 Refactoring.Guru – Factory Method Pattern![Attachment.tiff](file:///Attachment.tiff)
  • 🧱 Source example: Django ORM backend factory
尚無其他語言版本