設計模式是高級 PHP 面試必考,本文精選四大高頻模式,提供標準實現、應用場景、優缺點分析及面試話術。
核心意圖:類僅有一個實例,並提供全局訪問點。
<?php
class Database {
private static $instance = null;
private $pdo;
// 私有構造防止外部 new
private function __construct() {
$this->pdo = new PDO(
"mysql:host=localhost;dbname=test;charset=utf8mb4",
"root", "password",
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
}
// 防止克隆
private function __clone() {}
// 防止反序列化創建實例
public function __wakeup() {
throw new Exception("不能反序列化單例");
}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getPdo(): PDO {
return $this->pdo;
}
}
// 使用
$pdo = Database::getInstance()->getPdo();
$stmt = $pdo->query("SELECT 1");
?>
應用場景:數據庫連接、緩存客戶端、日誌記錄器、配置管理器。
面試加分點:提及 __clone/__wakeup 防破壞、依賴注入容器管理單例生命週期優於靜態單例、多線程環境下雙重檢查鎖(PHP 無原生多線程但 Swoole 需注意)。
核心意圖:定義創建對象接口,由子類決定實例化哪個類。
<?php
interface PaymentGateway {
public function pay(float $amount): bool;
}
class AlipayGateway implements PaymentGateway {
public function pay(float $amount): bool {
echo "支付寶支付 $amount 元\n";
return true;
}
}
class WechatGateway implements PaymentGateway {
public function pay(float $amount): bool {
echo "微信支付 $amount 元\n";
return true;
}
}
class PaymentFactory {
public static function create(string $type): PaymentGateway {
switch (strtolower($type)) {
case 'alipay': return new AlipayGateway();
case 'wechat': return new WechatGateway();
default: throw new InvalidArgumentException("不支持的支付類型: $type");
}
}
}
// 使用
$gateway = PaymentFactory::create('alipay');
$gateway->pay(99.00);
?>
變體:簡單工廠(靜態方法)、工廠方法(抽象工廠類+子類實現)、抽象工廠(創建產品族)。
應用場景:支付網關、日誌驅動、存儲適配器、消息隊列驅動。
核心意圖:定義算法族,封裝每個算法,使其可互換。
<?php
interface SortStrategy {
public function sort(array &$data): void;
}
class BubbleSort implements SortStrategy {
public function sort(array &$data): void {
$n = count($data);
for ($i = 0; $i < $n-1; $i++) {
for ($j = 0; $j < $n-$i-1; $j++) {
if ($data[$j] > $data[$j+1]) {
[$data[$j], $data[$j+1]] = [$data[$j+1], $data[$j]];
}
}
}
}
}
class QuickSort implements SortStrategy {
public function sort(array &$data): void {
$this->quickSort($data, 0, count($data)-1);
}
private function quickSort(array &$arr, int $low, int $high): void {
if ($low < $high) {
$pi = $this->partition($arr, $low, $high);
$this->quickSort($arr, $low, $pi-1);
$this->quickSort($arr, $pi+1, $high);
}
}
private function partition(array &$arr, int $low, int $high): int {
$pivot = $arr[$high];
$i = $low - 1;
for ($j = $low; $j < $high; $j++) {
if ($arr[$j] <= $pivot) {
$i++;
[$arr[$i], $arr[$j]] = [$arr[$j], $arr[$i]];
}
}
[$arr[$i+1], $arr[$high]] = [$arr[$high], $arr[$i+1]];
return $i + 1;
}
}
class SortContext {
private $strategy;
public function __construct(SortStrategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(SortStrategy $strategy): void {
$this->strategy = $strategy;
}
public function executeSort(array &$data): void {
$this->strategy->sort($data);
}
}
// 使用
$data = [64, 34, 25, 12, 22, 11, 90];
$context = new SortContext(new BubbleSort());
$context->executeSort($data); // 冒泡排序
$context->setStrategy(new QuickSort());
$context->executeSort($data); // 快速排序
?>
應用場景:排序算法、壓縮算法、路由選擇、促銷折扣計算、導航路徑規劃。
核心意圖:定義對象間一對多依賴,主體狀態變化自動通知觀察者。
<?php
interface Observer {
public function update(string $event, $data): void;
}
interface Subject {
public function attach(Observer $observer): void;
public function detach(Observer $observer): void;
public function notify(string $event, $data): void;
}
class OrderService implements Subject {
private $observers = [];
public function attach(Observer $observer): void {
$this->observers[] = $observer;
}
public function detach(Observer $observer): void {
$key = array_search($observer, $this->observers, true);
if ($key !== false) unset($this->observers[$key]);
}
public function notify(string $event, $data): void {
foreach ($this->observers as $observer) {
$observer->update($event, $data);
}
}
public function createOrder(array $orderData): int {
$orderId = rand(1000, 9999);
// 業務邏輯...
$this->notify('order.created', ['order_id' => $orderId, 'data' => $orderData]);
return $orderId;
}
}
class EmailNotifier implements Observer {
public function update(string $event, $data): void {
if ($event === 'order.created') {
echo "發送郵件通知:訂單 {$data['order_id']} 已創建\n";
}
}
}
class SmsNotifier implements Observer {
public function update(string $event, $data): void {
if ($event === 'order.created') {
echo "發送短信通知:訂單 {$data['order_id']} 已創建\n";
}
}
}
class LogObserver implements Observer {
public function update(string $event, $data): void {
error_log("[$event] " . json_encode($data));
}
}
// 使用
$orderService = new OrderService();
$orderService->attach(new EmailNotifier());
$orderService->attach(new SmsNotifier());
$orderService->attach(new LogObserver());
$orderService->createOrder(['user_id' => 1, 'amount' => 199]);
/* 輸出:
發送郵件通知:訂單 5432 已創建
發送短信通知:訂單 5432 已創建
(日誌寫入文件)
*/
?>
應用場景:事件驅動系統、異步任務觸發、緩存失效通知、模塊解耦。
熟練掌握這四大模式,能應對 80% 以上的設計模式面試題。