核心概念
- 介面 (Interface):定義契約,強制實作類別擁有特定方法
- 工廠 (Factory):封裝物件建立邏輯,呼叫端不需知悉具體類別
- 依賴倒置**:高層模組依賴抽象 (介面),不依賴具體實作
完整程式碼
<?php
// 1. 介面定義
interface Human {
public function getName(): string;
public function getGender(): string;
}
// 2. 具體實作
class Man implements Human {
public function getName(): string { return '我是男生'; }
public function getGender(): string { return 'Male'; }
}
class Woman implements Human {
public function getName(): string { return '我是女生'; }
public function getGender(): string { return 'Female'; }
}
// 3. 工廠類別
class HumanFactory {
public static function create(string $type = 'man'): ?Human {
return match (strtolower($type)) {
'man' => new Man(),
'woman' => new Woman(),
default => null,
};
}
// 便利方法
public static function createMan(): Human { return new Man(); }
public static function createWoman(): Human { return new Woman(); }
}
// 4. 使用端 (不依賴具體類別)
$human = HumanFactory::create('man');
echo $human->getName() . '<br>'; // 我是男生
$human = HumanFactory::create('woman');
echo $human->getName() . '<br>'; // 我是女生
// 型別提示依賴介面
function greet(Human $human): void {
echo "你好,{$human->getName()} ({$human->getGender()})<br>";
}
greet(HumanFactory::create('man'));
greet(HumanFactory::create('woman'));
進階:註冊表驅動工廠 (OCP 開放封閉原則)
<?php
class HumanFactory {
private static array $registry = [];
public static function register(string $type, string $class): void {
if (!is_subclass_of($class, Human::class)) {
throw new InvalidArgumentException("$class 必須實作 Human 介面");
}
self::$registry[strtolower($type)] = $class;
}
public static function create(string $type): ?Human {
$type = strtolower($type);
if (!isset(self::$registry[$type])) return null;
return new self::$registry[$type]();
}
}
// 啟動時註冊 (可從設定檔/模組動態載入)
HumanFactory::register('man', Man::class);
HumanFactory::register('woman', Woman::class);
// 新增類別無須修改工廠程式碼
HumanFactory::register('robot', Robot::class);
實務應用場景
| 場景 | 介面 | 實作類別 | 工廠決策依據 |
| 支付閘道 | PaymentGateway | PayPal, Stripe, NewebPay | 用戶選擇 / 幣別 / 國家 |
| 通知發送 | Notifier | Email, SMS, Line, Push | 通知類型 / 用戶偏好 |
| 報表匯出 | Exporter | Excel, PDF, CSV | 匯出格式參數 |
| 圖片處理 | ImageProcessor | GD, Imagick, Intervention | 伺服器環境 / 功能需求 |
關鍵優勢
- **解耦**:呼叫端只認介面,換實作不動呼叫碼
- **可測試**:單元測試可注入 Mock 實作
- **擴充**:新增類別只需註冊,符合開放封閉原則
- **集中管理**:建立邏輯 (單例、連線池、配置注入) 集中在工廠