核心:定義創建對象的接口,由子類/具體工廠決定實例化哪個類。降低調用者與具體類的耦合。
<?php
abstract class Operation {
abstract public function getValue(float $a, float $b): float;
public function getAttr(): int { return 1; }
}
class Add extends Operation {
public function getValue(float $a, float $b): float { return $a + $b; }
}
class Sub extends Operation {
public function getValue(float $a, float $b): float { return $a - $b; }
}
class Factory {
public static function create(string $op): ?Operation {
return match ($op) {
'+' => new Add(),
'-' => new Sub(),
default => null,
};
}
}
// 使用
$op = Factory::create('-');
echo $op->getValue(3, 6); // -3
<?php
interface Database {
public function connect(array $config): void;
public function query(string $sql): iterable;
}
class MySQLDatabase implements Database { /* ... */ }
class PgSQLDatabase implements Database { /* ... */ }
class SqliteDatabase implements Database { /* ... */ }
class DBFactory {
public static function create(string $driver, array $config): Database {
$instance = match ($driver) {
'mysql' => new MySQLDatabase(),
'pgsql' => new PgSQLDatabase(),
'sqlite' => new SqliteDatabase(),
default => throw new InvalidArgumentException("Unsupported driver: $driver"),
};
$instance->connect($config);
return $instance;
}
}
// 配置驅動
$db = DBFactory::create($_ENV['DB_DRIVER'], $_ENV['DB_CONFIG'] ?? []);
核心:構造方法私有、靜態實例屬性、靜態獲取方法、防止克隆/反序列化。
<?php
class Database {
private static ?self $instance = null;
private PDO $pdo;
private function __construct(array $config) {
$dsn = "mysql:host={$config['host']};dbname={$config['dbname']};charset=utf8mb4";
$this->pdo = new PDO($dsn, $config['user'], $config['pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
public static function getInstance(array $config = []): self {
if (self::$instance === null) {
if (empty($config)) throw new LogicException('首次調用需傳入配置');
self::$instance = new self($config);
}
return self::$instance;
}
// 防止克隆
private function __clone() {}
// 防止反序列化
public function __wakeup() {
throw new Exception("不能反序列化單例");
}
public function getPDO(): PDO { return $this->pdo; }
}
// 使用
$db = Database::getInstance($config);
$stmt = $db->getPDO()->query('SELECT 1');
<?php
class ConnectionPool {
private static array $instances = [];
public static function get(string $name, array $config): Database {
if (!isset(self::$instances[$name])) {
self::$instances[$name] = Database::getInstance($config); // 單例按名稱區分
}
return self::$instances[$name];
}
}
// 主庫、從庫、不同業務庫
$master = ConnectionPool::get('master', $masterConfig);
$slave = ConnectionPool::get('slave', $slaveConfig);
match 表達式、readonly 類、interface 契約、依賴注入容器(如 PHP-DI、Symfony DI)管理工廠本身。$container->get(Database::class) 由容器控制實例化策略(單例、原型、請求作用域)。#[Singleton] 配合編譯時/運行時分析工具標記。| 模式 | 核心目的 | 關鍵代碼點 | 現代建議 |
|---|---|---|---|
| 工廠 | 解耦創建邏輯 | 靜態創建方法、介面/抽象類 | 廣泛使用,配合 DI 容器 |
| 單例 | 保證全局唯一 | 私有構造、靜態實例、防克隆 | **謹慎使用**,優先 DI 容器管理 |