設計模式是軟體開發的通用解決方案。PHP開發中最常用的三大模式——單例、工廠、觀察者——分別解決資源唯一存取、物件建立解耦、事件驅動通訊三大核心需求。本文提供完整可執行實作代碼。
適用場景:資料庫連線、配置管理、日誌記錄器等資源密集型服務。
三大要素:
private __construct())防止外部實例化getInstance())提供存取點PHP特有防禦:私有 __clone() 防止複製。
class Database {
private static $instance;
private function __construct() { /* 連線邏輯 */ }
private function __clone() { /* 防止克隆 */ }
public static function getInstance() {
if (!(self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
}
$a = Database::getInstance();
$b = Database::getInstance();
var_dump($a === $b); // true - 同一實例
核心思想:根據輸入參數或配置,回傳對應介面的實作物件,呼叫端無需知道具體類別。
interface Shape {
public function getArea();
public function getCircumference();
}
class Rectangle implements Shape {
private $width, $height;
public function __construct($w, $h) { $this->width=$w; $this->height=$h; }
public function getArea() { return $this->width * $this->height; }
public function getCircumference() { return 2*($this->width + $this->height); }
}
class Circle implements Shape {
private $radius;
public function __construct($r) { $this->radius=$r; }
public function getArea() { return M_PI * pow($this->radius, 2); }
public function getCircumference() { return 2 * M_PI * $this->radius; }
}
class ShapeFactory {
public static function create() {
$args = func_get_args();
switch (count($args)) {
case 1: return new Circle($args[0]);
case 2: return new Rectangle($args[0], $args[1]);
default: throw new InvalidArgumentException('參數錯誤');
}
}
}
$rect = ShapeFactory::create(5, 5); // Rectangle
$circle = ShapeFactory::create(4); // Circle
核心角色:
update() 回應事件interface Observer {
public function onListen($sender, $args);
public function getObserverName();
}
interface Observable {
public function addObserver(Observer $o);
public function removeObserver($name);
}
abstract class BaseObserver implements Observer {
protected $observer_name;
public function getObserverName() { return $this->observer_name; }
}
abstract class BaseObservable implements Observable {
protected $observers = [];
public function addObserver(Observer $o) { $this->observers[] = $o; }
public function removeObserver($name) {
foreach ($this->observers as $i => $o) {
if ($o->getObserverName() === $name) {
array_splice($this->observers, $i, 1);
break;
}
}
}
}
class EventSource extends BaseObservable {
public function trigger($event) {
foreach ($this->observers as $o) {
$o->onListen($this, $event);
}
}
}
class Logger extends BaseObserver {
protected $observer_name = 'Logger';
public function onListen($sender, $args) {
echo "[Log] Event: $args\n";
}
}
class Notifier extends BaseObserver {
protected $observer_name = 'Notifier';
public function onListen($sender, $args) {
echo "[Notify] Pushed: $args\n";
}
}
// 使用
$source = new EventSource();
$source->addObserver(new Logger());
$source->addObserver(new Notifier());
$source->trigger('UserLogin'); // 兩個觀察者皆收到通知
| 模式 | 解決問題 | 關鍵詞 |
|---|---|---|
| 單例 | 全域唯一存取、資源共享 | getInstance、private constructor |
| 工廠 | 物件建立邏輯集中、解耦具體類別 | 介面、多型、參數驅動 |
| 觀察者 | 事件驅動、鬆耦合通訊 | 訂閱/發布、事件循環 |