前言
依賴注入(Dependency Injection)是軟體開發中一種重要的設計模式,它的核心思想非常簡單:一個類不應該負責創建自己所需的依賴對象,而應該從外部接收它們。這種模式有效地實現了「控制反轉」(IoC) 原則,將對象創建的責任從類本身轉移到外部框架或容器。
什麼是依賴注入?
依賴注入是控制反轉(IoC)的一種實現形式,它將對象的創建和管理責任從類內部轉移到外部。這種簡單的模式帶來了幾個關鍵好處
- 解耦
- 可測試性提高
- 配置集中化
- 更好的關注點分離
舉個例子,一般來說,我們會直在在 class 直接實例化數據庫連接:
class UserService:
def __init__(self):
self.db = Database() # 直接創建依賴
def get_user(self, user_id):
return self.db.find_user(user_id)而使用依賴注入後,程式碼會變成:
class UserService:
def __init__(self, db): # 依賴從外部注入
self.db = db
def get_user(self, user_id):
return self.db.find_user(user_id)這個設計實現了控制反轉原則,假如團隊之後想換資料庫,這樣的寫法不僅更靈活(可以替換成不同的資料庫),在寫單元測試時也更容易測試(可以注入測試用的資料庫),以及模組間的依賴關係也一目了然。
儘管依賴注入在 Java、C# 等語言中已經成為標準實踐,但在 Python 專案中卻相對罕見。
👉 延伸閱讀:淺談單元測試的重要性
為什麼依賴注入在 Python 專案中較不常見?
- 專案規模通常較小:相較於 Java、C# 而言,Python 的專案規模通常較小,不需要太複雜的依賴關係,且這樣的專案會比較要求執行效率,導入 DI 增加的額外開銷也是一個考量之一。
- 模組系統的便利性:Python 的模組能夠直接匯入並使用模組中的物件,這種方式就已經提供了一種簡單的依賴管理機制。
- 動態程式語言特性:動態程式語言和弱型別的特性可以讓我們簡單替換物件。
- 許多替代方案:Python 提供了其他方式來實現類似 DI 的效果,例如使用函數參數、裝飾器或上下文管理器等,這些方式更符合 Python 的風格,也更有可讀性。
Python 的 import 可以動態決定導入哪個模組:
# 動態決定導入哪個模組
if config.use_postgres:
from .postgres_db import Database
else:
from .sqlite_db import Database在 Java 需要依賴注入框架處理的事,Python 可能只需一行程式碼:
def process_data(database=get_default_database()):
# 可以直接使用 database 或預設值總結
最後,是否採用依賴注入還是要考慮專案的具體需求、團隊的技術背景以及長期維護的考量,依賴注入在 Python 專案中雖然少見,但在複雜的商業邏輯中仍然是一個非常好的設計,當依賴關係變得越來越複雜時,才是依賴注入發揮的開始。

