Factory Method Pattern,PHP 工廠模式

簡介
Factory Method Pattern(工廠方法模式)是一種專門用於處理物件創建問題的設計模式。本文將先解釋什麼是 Factory Method Pattern,然後用一個簡單易懂的例子來說明其運作方式。接著會說明什麼情況下應該使用這個模式,並通過一個以咖啡為主題的 PHP 程式範例來進一步說明。最後會比較 Factory Method Pattern 和其他類似的設計模式,幫助讀者更好地理解它們之間的差異。
什麼是 Factory Method Pattern
Factory Method Pattern 是一種創建型設計模式,它提供了一個介面用於創建物件,但允許子類別改變將要創建的物件的類型。透過這種方式,我們可以將物件創建的程式碼和實際使用物件的程式碼分離,大幅增加了程式碼的靈活性和可維護性。
生活中的例子:
想像你走進一家咖啡店,你不需要知道咖啡是如何製作的,只需要點單即可。咖啡店(Factory)會根據你的需求(參數)為你製作一杯咖啡(物件)。你不需要了解咖啡的製作過程,只需要知道你想要什麼類型的咖啡,工廠就會為你處理所有的細節。
什麼狀況適合使用 Factory Method Pattern
當你有一個超類別,它有多個子類別,並且基於某些條件,你必須返回其中一個子類別的實例時,最好使用 Factory Method Pattern。這樣可以隱藏實例創建的邏輯,並使程式碼更容易擴展。
適用情境:
- 當你需要在執行時期決定要創建哪種類型的物件時
- 當物件創建的邏輯變得複雜,需要集中管理時
- 當你想要降低程式碼之間的耦合度時
- 當你預期未來可能需要新增新的物件類型時
例如,一個咖啡店可能有多種咖啡,每種咖啡的製作過程都略有不同。使用 Factory Method,我們可以輕鬆地新增更多種咖啡,而不影響現有程式碼。當需要新增新的咖啡類型時,只需要在工廠類別中添加新的創建邏輯,而不需要修改使用咖啡的程式碼。
範例教學
在這個範例中,我們會創建一個 CoffeeFactory 類別,它可以根據不同的需求製作不同種類的咖啡。我們將從一個簡單的範例開始,然後逐步改善它,展示 Factory Method Pattern 的優勢。
原始範例,未使用 Factory Method
<?php
class Coffee {
public function brew() {
echo "Brewing a regular coffee\n";
}
}
$coffee = new Coffee();
$coffee->brew();
?>
缺點
這種方式的主要缺點是它不夠靈活。如果我們想添加更多種咖啡,必須在每個需要的地方自己創建物件實例,這會導致程式碼重複,並且增加了維護的困難度。如果使用工廠模式,就不必深入了解各種不同的咖啡類別,可以降低物件間的耦合,讓程式碼更加模組化和易於維護。
改善範例,使用 Factory Method
<?php
interface Coffee {
public function brew();
}
class RegularCoffee implements Coffee {
public function brew() {
echo "Brewing a regular coffee\n";
}
}
class Espresso implements Coffee {
public function brew() {
echo "Brewing an espresso\n";
}
}
class CoffeeFactory {
public static function createCoffee($type) {
if ($type === 'regular') {
return new RegularCoffee();
} elseif ($type === 'espresso') {
return new Espresso();
}
throw new InvalidArgumentException("Unknown coffee type: $type");
}
}
$coffee = CoffeeFactory::createCoffee('espresso');
$coffee->brew();
?>

咖啡工廠類別圖
優點
使用 Factory Method Pattern 帶來以下好處:
- 降低耦合度:使用咖啡的程式碼不需要直接依賴具體的咖啡類別,只需要依賴
Coffee介面 - 易於擴展:當需要新增新的咖啡類型時,只需要在工廠類別中添加新的創建邏輯,不需要修改使用咖啡的程式碼
- 集中管理:所有物件創建的邏輯都集中在工廠類別中,更容易維護和測試
- 提高靈活性:可以根據不同的條件動態創建不同類型的物件
更多延伸範例
我們可以繼續擴展這個範例,例如添加一個 Latte(拿鐵)類別。這個例子展示了 Factory Method Pattern 的擴展性。
class Latte implements Coffee {
public function brew() {
echo "Brewing a latte\n";
}
}
// 更新 CoffeeFactory
class CoffeeFactory {
public static function createCoffee($type) {
if ($type === 'regular') {
return new RegularCoffee();
} elseif ($type === 'espresso') {
return new Espresso();
} elseif ($type === 'latte') {
return new Latte();
}
throw new InvalidArgumentException("Unknown coffee type: $type");
}
}
// 工廠現在可以生產拿鐵,使用者只需知道拿鐵的名稱即可,不需要了解工廠背後的運作細節
$coffee = CoffeeFactory::createCoffee('latte');
$coffee->brew();
從這個例子可以看出,當我們需要新增新的咖啡類型時,只需要:
- 創建新的咖啡類別並實作
Coffee介面 - 在工廠類別中添加創建該類別的邏輯
使用咖啡的程式碼完全不需要修改,這就是 Factory Method Pattern 帶來的靈活性。
其他類似的 Design Pattern
Factory Method Pattern 和 Abstract Factory Pattern 都是用於創建物件的設計模式,但它們的應用場景不同。
主要區別:
- Factory Method Pattern:用於創建單一類型的物件。它透過一個方法來創建物件,讓子類別決定要實例化哪個類別。
- Abstract Factory Pattern:用於創建一系列相關或依賴的物件。它提供一個介面來創建多個相關的物件,而不需要指定它們的具體類別。
| Design Pattern | 主要用途 | 適用情境 |
|---|---|---|
| Factory Method | 創建單一類型的物件 | 當需要根據條件創建不同類型的物件時 |
| Abstract Factory | 創建一系列相關的物件 | 當需要創建多個相關或依賴的物件時 |
選擇建議:
- 如果你只需要創建單一類型的物件,使用 Factory Method Pattern
- 如果你需要創建一組相關的物件(例如,創建一套 UI 元件),使用 Abstract Factory Pattern
總結
Factory Method Pattern 是一個非常實用的設計模式,它能夠:
- 將物件創建的邏輯與使用物件的程式碼分離
- 降低程式碼之間的耦合度
- 提高程式碼的可維護性和擴展性
- 讓程式碼更加模組化和易於測試
當你需要在執行時期根據條件創建不同類型的物件時,Factory Method Pattern 是一個很好的選擇。它讓你的程式碼更加靈活,也更容易應對未來的需求變化。
參考來源
- Wikipedia: Factory Method Pattern
- GeeksforGeeks: Factory Method Pattern
- Refactoring Guru: Factory Method
- Tutorialspoint: Factory Method Pattern
- Stack Overflow: What is Factory Method Pattern?
- ← Previous
Singleton Pattern,PHP 單例模式 - Next →
Null Object Pattern,PHP 空物件模式

