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

PHP 設計模式實戰:觀察者、策略與簡單工廠模式完整實作

     編輯:PHP 綜合知識

三大經典設計模式 PHP 實作全解析

設計模式是軟體開發的通用解決方案詞彙。本文詳細實作 觀察者模式、策略模式、簡單工廠模式,並說明適用場景與比較。


一、觀察者模式

定義:物件間一對多依賴,主題狀態變更時自動通知所有觀察者。

適用:事件系統、訂閱通知、MVC View 更新、日誌記錄、快取失效。

完整實作

<?php
// 1. 主題介面
interface Subject {
    public function attach(Observer $observer): void;
    public function detach(Observer $observer): void;
    public function notify(): void;
    public function setState(string $state): void;
    public function getState(): string;
}

// 2. 具體主題:老闆
class Boss implements Subject {
    private string $state = '';
    /** @var Observer[] */
    private array $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(): void {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
    
    public function setState(string $state): void {
        $this->state = $state;
        $this->notify(); // 狀態變更自動通知
    }
    
    public function getState(): string {
        return $this->state;
    }
}

// 3. 觀察者介面
interface Observer {
    public function update(Subject $subject): void;
}

// 4. 具體觀察者:股票觀察員
class StockObserver implements Observer {
    private string $name;
    
    public function __construct(string $name) {
        $this->name = $name;
    }
    
    public function update(Subject $subject): void {
        echo "[{$this->name}] 收到通知: 老闆狀態變為 '{$subject->getState()}',趕快跑!\n";
    }
}

// 5. 客戶端使用
$boss = new Boss();

$observer1 = new StockObserver("三毛");
$observer2 = new StockObserver("小李");

$boss->attach($observer1);
$boss->attach($observer2);
// 重複加入會被允許 (可依需求去重)

$boss->setState("警察來了"); 
// 輸出:
// [三毛] 收到通知: 老闆狀態變為 '警察來了',趕快跑!
// [小李] 收到通知: 老闆狀態變為 '警察來了',趕快跑!

$boss->detach($observer1);
$boss->setState("安全了");
// 僅 [小李] 收到通知
?>

二、策略模式

定義:定義演算法族群,封裝每個演算法,使它們可互換。讓演算法獨立於使用它的客戶端。

適用:支付方式、排序演算法、壓縮策略、路由演算法、驗證規則。

完整實作

<?php
// 1. 策略介面
interface SortStrategy {
    public function sort(array $data): array;
}

// 2. 具體策略
class BubbleSort implements SortStrategy {
    public function sort(array $data): array {
        $len = count($data);
        for ($i = 0; $i < $len; $i++) {
            for ($j = 0; $j < $len - $i - 1; $j++) {
                if ($data[$j] > $data[$j+1]) {
                    [$data[$j], $data[$j+1]] = [$data[$j+1], $data[$j]];
                }
            }
        }
        return $data;
    }
}

class QuickSort implements SortStrategy {
    public function sort(array $data): array {
        if (count($data) <= 1) return $data;
        $pivot = $data[0];
        $left = $right = [];
        for ($i = 1; $i < count($data); $i++) {
            $data[$i] < $pivot ? $left[] = $data[$i] : $right[] = $data[$i];
        }
        return array_merge($this->sort($left), [$pivot], $this->sort($right));
    }
}

class NativeSort implements SortStrategy {
    public function sort(array $data): array {
        sort($data);
        return $data;
    }
}

// 3. 環境類別
class SortContext {
    private SortStrategy $strategy;
    
    public function __construct(SortStrategy $strategy) {
        $this->strategy = $strategy;
    }
    
    public function setStrategy(SortStrategy $strategy): void {
        $this->strategy = $strategy;
    }
    
    public function executeSort(array $data): array {
        return $this->strategy->sort($data);
    }
}

// 4. 客戶端使用
$data = [5, 2, 8, 1, 9, 3];

$context = new SortContext(new BubbleSort());
echo "Bubble: " . implode(',', $context->executeSort($data)) . "\n";

$context->setStrategy(new QuickSort());
echo "Quick:  " . implode(',', $context->executeSort($data)) . "\n";

$context->setStrategy(new NativeSort());
echo "Native: " . implode(',', $context->executeSort($data)) . "\n";
?>

三、簡單工廠模式

定義:由一個工廠類別根據參數決定建立哪個產品類別實例。屬創建型模式,非 GoF 23 種正式模式,但極實用。

適用:資料庫連接、日誌驅動、圖片處理器、API 客戶端、支付閘道。

完整實作

<?php
// 1. 產品介面
interface Database {
    public function connect(): void;
    public function query(string $sql): array;
}

// 2. 具體產品
class MySQLDatabase implements Database {
    public function connect(): void { echo "MySQL 連接成功\n"; }
    public function query(string $sql): array { return ["MySQL 結果: $sql"]; }
}

class PostgreSQLDatabase implements Database {
    public function connect(): void { echo "PostgreSQL 連接成功\n"; }
    public function query(string $sql): array { return ["PostgreSQL 結果: $sql"]; }
}

class SQLiteDatabase implements Database {
    public function connect(): void { echo "SQLite 連接成功\n"; }
    public function query(string $sql): array { return ["SQLite 結果: $sql"]; }
}

// 3. 簡單工廠
class DatabaseFactory {
    public static function create(string $type): Database {
        return match(strtolower($type)) {
            'mysql'      => new MySQLDatabase(),
            'postgresql' => new PostgreSQLDatabase(),
            'sqlite'     => new SQLiteDatabase(),
            default      => throw new InvalidArgumentException("不支援的資料庫類型: $type"),
        };
    }
}

// 4. 客戶端使用
$dbType = $_ENV['DB_TYPE'] ?? 'mysql'; // 從環境變數決定
$db = DatabaseFactory::create($dbType);
$db->connect();
$results = $db->query("SELECT * FROM users");
print_r($results);
?>

三大模式比較總結

維度 觀察者模式 策略模式 簡單工廠模式
分類 行為型 行為型 創建型 (非 GoF)
核心目的 物件間鬆耦合通知 演算法可互換 集中物件建立邏輯
關鍵角色 Subject, Observer Strategy, Context Factory, Product
耦合度 主題僅知介面 環境僅知策略介面 客戶端僅知工廠
擴展性 新增觀察者不修改主題 新增策略不修改環境 新增產品修改工廠 (違反 OCP)
典型應用 事件總線、MVC 排序、支付、壓縮 DB連接、Logger、Driver

進階:結合使用

<?php
// 策略 + 工廠:根據配置自動選擇策略
class PaymentContext {
    private PaymentStrategy $strategy;
    
    public function __construct(string $gateway) {
        $this->strategy = PaymentFactory::create($gateway);
    }
    
    public function pay(float $amount): bool {
        return $this->strategy->pay($amount);
    }
}

// 觀察者 + 策略:不同觀察者使用不同策略處理通知
class EmailObserver implements Observer {
    private NotificationStrategy $strategy;
    public function __construct(NotificationStrategy $s) { $this->strategy = $s; }
    public function update(Subject $s): void { $this->strategy->send($s->getState()); }
}
?>
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved