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

PHP 設計模式精要:單例、工廠、觀察者三大核心模式完整實作

     編輯:PHP 綜合知識

設計模式是解決特定問題的可復用方案。PHP 開發中最常落地的三大模式——單例、工廠、觀察者——涵蓋資源控制、物件創建解耦、事件驅動架構三大核心需求。本文提供生產級實作代碼與應用場景分析。

1. 單例模式 —— 確保全域唯一實例

適用場景:資料庫連線、配置管理、日誌記錄器、快取客戶端。

<?php
final 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,
            PDO::ATTR_EMULATE_PREPARES   => false,
        ]);
    }

    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() {} // 禁止克隆
    private function __wakeup() {} // 禁止反序列化

    public function getPdo(): PDO { return $this->pdo; }
}

// 使用
$db = Database::getInstance($config)->getPdo();

2. 工廠模式 —— 封裝物件創建邏輯

適用場景:支援多種驅動(資料庫、快取、儲存)、依據配置動態實例化、統一建構複雜物件。

<?php
interface LoggerInterface { public function log(string $level, string $msg): void; }

class FileLogger implements LoggerInterface {
    public function __construct(private string $path) {}
    public function log(string $level, string $msg): void {
        file_put_contents($this->path, "[$level] $msg\n", FILE_APPEND | LOCK_EX);
    }
}

class SyslogLogger implements LoggerInterface {
    public function log(string $level, string $msg): void {
        syslog(LOG_INFO, "[$level] $msg");
    }
}

class LoggerFactory
{
    public static function create(string $driver, array $config = []): LoggerInterface
    {
        return match ($driver) {
            'file'   => new FileLogger($config['path'] ?? '/var/log/app.log'),
            'syslog' => new SyslogLogger(),
            default  => throw new InvalidArgumentException("Unknown logger: $driver"),
        };
    }
}

// 使用
$logger = LoggerFactory::create('file', ['path' => '/var/log/myapp.log']);
$logger->log('INFO', 'Application started');

3. 觀察者模式 —— 解耦事件發送與處理

適用場景:用戶註冊後發送歡迎信、寫入審計日誌、更新搜尋索引、清除快取等副作用邏輯。

<?php
interface EventListener { public function handle(string $event, array $payload): void; }

class EventDispatcher
{
    /** @var array */
    private array $listeners = [];

    public function subscribe(string $event, EventListener $listener): void
    {
        $this->listeners[$event][] = $listener;
    }

    public function dispatch(string $event, array $payload = []): void
    {
        foreach ($this->listeners[$event] ?? [] as $listener) {
            $listener->handle($event, $payload);
        }
    }
}

// 具體監聽器
class WelcomeEmailListener implements EventListener {
    public function handle(string $event, array $payload): void {
        if ($event === 'user.registered') {
            mail($payload['email'], 'Welcome!', "Hi {$payload['name']}...");
        }
    }
}

class AuditLogListener implements EventListener {
    public function handle(string $event, array $payload): void {
        file_put_contents('/var/log/audit.log', json_encode([$event, $payload, time()]) . "\n", FILE_APPEND);
    }
}

// 組裝
$dispatcher = new EventDispatcher();
$dispatcher->subscribe('user.registered', new WelcomeEmailListener());
$dispatcher->subscribe('user.registered', new AuditLogListener());

// 觸發
$dispatcher->dispatch('user.registered', ['id' => 123, 'name' => 'John', 'email' => 'john@example.com']);

模式選擇決策表

需求推薦模式核心關鍵字
全域唯一、延遲初始化、受控存取單例private constructor, static getInstance()
依條件創建同介面不同實現、隱藏建構細節工廠interface, factory method, configuration driven
一對多通知、鬆耦合、事件驅動觀察者subscribe, dispatch, listener, event

掌握三大模式,即可應對 80% 以上的架構級設計決策。切記:模式是手段,解決問題才是目的,勿為用模式而用模式。

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