單例模式確保一個類別在全域僅有一個實例,並提供全域存取點。常用於資料庫連線、配置管理、日誌記錄器等場景。本文從核心程式碼到原理逐層拆解。
<?php
final class Database {
private static ?self $instance = null;
// 私有建構子,防止外部 new
private function __construct() {
// 實際連線邏輯:PDO、mysqli 等
}
// 禁止克隆
private function __clone() {}
// 禁止反序列化
public function __wakeup() {
throw new \Exception("Cannot unserialize singleton");
}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 業務方法範例
public function query(string $sql): array {
// ...
return [];
}
}
// 使用方式
$db = Database::getInstance();
$db->query('SELECT 1');
?>
new Database()。clone $db。unserialize() 重建實例。PHP 單執行緒模型下上述寫法足夠。若使用 Swoole/RoadRunner 等多執行緒環境,需加入鎖機制:
public static function getInstance(): self {
if (self::$instance === null) {
$lock = Lock::acquire('db_singleton');
if (self::$instance === null) { // Double-check
self::$instance = new self();
}
$lock->release();
}
return self::$instance;
}
現代框架(Laravel、Symfony)傾向用服務容器管理單例生命週期,而非硬編碼單例類別,便於測試與解耦。