單例模式確保一個類別僅有一個實例,並提供全域存取點。常用於資料庫連線、日誌記錄、設定管理等全域共享資源。本文展示標準 PHP 單例實作,並說明關鍵細節。
<?php
class Singleton {
// 唯一實例靜態屬性
private static ?self $instance = null;
// 範例業務屬性
private string $name = '';
// 私有建構子,防止外部 new
private function __construct() {}
// 防止複製
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 getName(): string {
return $this->name;
}
public function setName(string $name): void {
$this->name = $name;
}
}
// 使用範例
$s1 = Singleton::getInstance();
$s1->setName('first');
echo "s1 name: {$s1->getName()}\n"; // first
unset($s1); // 釋放變數,但靜態實例仍存在
$s2 = Singleton::getInstance();
echo "s2 name: {$s2->getName()}\n"; // first(同一實例)
echo "同一實例? " . ($s1 === $s2 ? '是' : '否') . "\n"; // 是
?>
new Singleton()。clone $singleton。unserialize() 重建實例。?self、string 等型別提示。PHP 為單執行緒模型(CLI/FPM),getInstance() 的 if (null) 檢查足夠。若使用 Swoole/RoadRunner 等多執行緒環境,需加鎖:
public static function getInstance(): self {
if (self::$instance === null) {
// 簡易鎖(僅示意,生產環境請用 Mutex/Semaphore)
$lock = fopen(__FILE__, 'r');
flock($lock, LOCK_EX);
if (self::$instance === null) {
self::$instance = new self();
}
flock($lock, LOCK_UN);
fclose($lock);
}
return self::$instance;
}
單例模式在 PHP 中實作簡單,但需謹慎使用。掌握私有建構子、防複製、防反序列化三大要素,即可寫出健壯的單例類別。希望本文對您的 PHP 程式設計有所幫助。