<?php
class Example {
private static $_instance = null;
private function __construct()
{
echo 'I am Constructed';
}
public static function singleton()
{
if (!isset(self::$_instance)) {
$c = __CLASS__;
self::$_instance = new $c();
}
return self::$_instance;
}
public function __clone()
{
trigger_error('Clone is not allowed', E_USER_ERROR);
}
public function test()
{
echo "test";
}
}
// 錯誤寫法:建構子為 private,無法 new
// $test = new Example;
// 正確取得單例
$test = Example::singleton();
$test->test();
// 複製會觸發錯誤
// $test_clone = clone $test;
雖然 PHP 每次請求結束會釋放所有記憶體,單例無法跨請求複用,但在單次請求生命週期內仍具價值:
new PDO 或 mysqli_connect,節省連線開銷FrontController,集中管理路由、插件、回應物件var_dump<?php
abstract class Singleton {
private static $instances = [];
protected function __construct() {}
final public function __clone() {
trigger_error('Clone not allowed', E_USER_ERROR);
}
final public function __wakeup() {
trigger_error('Unserialize not allowed', E_USER_ERROR);
}
public static function getInstance()
{
$cls = get_called_class();
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new $cls();
}
return self::$instances[$cls];
}
}
class Database extends Singleton {
protected $pdo;
protected function __construct() {
$this->pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
}
public function getPdo() { return $this->pdo; }
}
// 使用
$db = Database::getInstance();
掌握單例模式能有效控制資源存取,是 PHP 進階開發必備技能。