單例模式確保一個類只有一個實例,並提供全域存取點。雖然看似方便,但資深架構師 Scott Densmore(翻譯自 Brian Button 觀點)指出:單例模式本質上是披著設計模式外衣的全域變數,會嚴重破壞軟體設計的核心原則。以下是四大核心罪狀:
單例提供全域存取點,讓你不必傳遞參考。但這與全域變數無異:
單例類別同時承擔兩個職責:
正確做法:將建立與存取控制移至工廠或建構器,讓業務類別專注於業務。
Singleton::getInstance()),無法透過多型替換為 Mock/Stub。| 場景 | 反模式 | 推薦模式 |
|---|---|---|
| 共享服務存取 | Singleton::getInstance() | 依賴注入容器管理單一實例生命週期 |
| 限制實例數量 | 類別內部控制 | 工廠模式 / 建構器模式 |
| 跨層級傳遞資料 | 全域單例當作資料袋 | 明確傳遞 DTO / Value Object |
單例模式並非絕對不可用,但在現代 PHP 應用(特別是採用 DI 容器的框架如 Laravel、Symfony)中,**幾乎總有更優雅、可測試、可維護的替代方案**。下次想寫 private static $instance 時,請三思:是否真的是設計需要,還是只是圖省事?