設計模式是面試必考、重構利器。本文精選 PHP 開發最高頻的 **單例、工廠、組合、策略** 四大模式,提供可直接執行的完整代碼、UML 關係說明與實戰應用場景。
private __construct()private __clone()private static $instancepublic static getInstance()class SinglePDO {
private static ?self $_instance = null;
private PDO $_pdo;
private function __construct(string $dsn, string $user, string $pass) {
try {
$this->_pdo = new PDO($dsn, $user, $pass);
$this->_pdo->exec('SET NAMES utf8mb4');
$this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("DB Connect Failed: {$e->getMessage()}");
}
}
private function __clone() {} // 禁止克隆
public static function getInstance(string $dsn, string $user, string $pass): self {
if (self::$_instance === null) {
self::$_instance = new self($dsn, $user, $pass);
}
return self::$_instance;
}
public function execute(string $sql): int|false {
return $this->_pdo->exec($sql);
}
public function query(string $sql): PDOStatement {
return $this->_pdo->query($sql);
}
}
// 使用
$pdo = SinglePDO::getInstance('mysql:host=localhost;dbname=test', 'root', '');
$pdo->execute("DELETE FROM user WHERE id = 1");
支援多組不同 DSN 連線:
class MultiPDO {
private static array $instances = [];
private function __construct(private string $dsn, private string $user, private string $pass) {}
public static function getInstance(string $dsn, string $user, string $pass): self {
$key = md5($dsn . $user);
if (!isset(self::$instances[$key])) {
self::$instances[$key] = new self($dsn, $user, $pass);
}
return self::$instances[$key];
}
}
interface PaymentGateway {
public function pay(float $amount): bool;
}
class Alipay implements PaymentGateway { public function pay(float $amount): bool { /* ... */ return true; } }
class WechatPay implements PaymentGateway { public function pay(float $amount): bool { /* ... */ return true; } }
class PaymentFactory {
public static function create(string $type): PaymentGateway {
return match ($type) {
'alipay' => new Alipay(),
'wechat' => new WechatPay(),
default => throw new InvalidArgumentException("Unknown gateway: $type"),
};
}
}
// 使用
$gateway = PaymentFactory::create('alipay');
$gateway->pay(99.00);
abstract class PaymentFactoryBase {
abstract protected function createGateway(): PaymentGateway;
public function processPayment(float $amount): bool {
$gateway = $this->createGateway();
return $gateway->pay($amount);
}
}
class AlipayFactory extends PaymentFactoryBase {
protected function createGateway(): PaymentGateway { return new Alipay(); }
}
interface FileSystemComponent {
public function getName(): string;
public function getSize(): int;
public function display(int $depth = 0): void;
}
class File implements FileSystemComponent {
public function __construct(private string $name, private int $size) {}
public function getName(): string { return $this->name; }
public function getSize(): int { return $this->size; }
public function display(int $depth = 0): void {
echo str_repeat(' ', $depth) . "📄 {$this->name} ({$this->size} KB)" . PHP_EOL;
}
}
class Directory implements FileSystemComponent {
private array $children = [];
public function __construct(private string $name) {}
public function add(FileSystemComponent $component): void {
$this->children[] = $component;
}
public function getName(): string { return $this->name; }
public function getSize(): int {
return array_reduce($this->children, fn($sum, $c) => $sum + $c->getSize(), 0);
}
public function display(int $depth = 0): void {
echo str_repeat(' ', $depth) . "📁 {$this->name}" . PHP_EOL;
foreach ($this->children as $child) {
$child->display($depth + 1);
}
}
}
// 使用
$root = new Directory('root');
$root->add(new File('index.php', 10));
$src = new Directory('src');
$src->add(new File('User.php', 5));
$src->add(new File('Post.php', 8));
$root->add($src);
$root->display();
interface SortStrategy {
public function sort(array $data): array;
}
class BubbleSort implements SortStrategy {
public function sort(array $data): array {
// 簡化示意
sort($data);
return $data;
}
}
class QuickSort implements SortStrategy {
public function sort(array $data): array {
// 簡化示意
sort($data, SORT_NUMERIC);
return $data;
}
}
class SortContext {
public function __construct(private SortStrategy $strategy) {}
public function setStrategy(SortStrategy $strategy): void {
$this->strategy = $strategy;
}
public function execute(array $data): array {
return $this->strategy->sort($data);
}
}
// 使用
$context = new SortContext(new QuickSort());
$sorted = $context->execute([3,1,4,1,5,9]);
$context->setStrategy(new BubbleSort());
$sorted = $context->execute(['c','a','b']);
| 模式 | 核心目的 | 關鍵結構 | 典型應用 |
|---|---|---|---|
| 單例 | 全域唯一存取點 | 私有建構子 + 靜態實例 | DB連線、快取、日誌、配置 |
| 工廠 | 解耦建立邏輯 | 介面 + 多實作 + 工廠類 | 支付閘道、驅動載入、文檔解析器 |
| 組合 | 部分-整體樹形結構 | 統一介面 + 遞歸組合 | 選單、目錄、組織架構、AST |
| 策略 | 演算法可互換 | 策略介面 + 多具體策略 + Context | 排序、壓縮、路由演算、驗證規則 |
掌握這四大模式,即能應對 80% 以上的 PHP 面試設計模式題目,更能在重構舊代碼時游刃有餘。記住:**模式是為了解決具體問題而生,不要為了用模式而用模式。**