首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 設計模式面試精講:單例、工廠、策略、觀察者四大核心模式實戰

     編輯:PHP 相關知識

PHP 設計模式面試精講:單例、工廠、策略、觀察者四大核心模式實戰

設計模式是高級 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 已創建
(日誌寫入文件)
*/
?>

應用場景:事件驅動系統、異步任務觸發、緩存失效通知、模塊解耦。

面試回答框架

  1. 定義:一句話說清核心意圖
  2. 結構:角色組成(接口/抽象類/具體類)
  3. 代碼:寫出關鍵實現(單例 getInstance、工廠 create、策略 setStrategy、觀察者 attach/notify)
  4. 場景:列舉 2-3 個實際業務場景
  5. 優缺點:單例難測試、工廠增加複雜度、策略類膨脹、觀察者循環引用/性能
  6. 擴展:提及 Laravel 服務容器實現單例/工廠、事件系統實現觀察者、中間件模式關係

熟練掌握這四大模式,能應對 80% 以上的設計模式面試題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved