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

PHP 單例模式最佳實踐:利用靜態延遲綁定實現可復用基類(PHP 5.3+)

     編輯:PHP 綜合知識

經典寫法的致命缺陷

class A {
    protected static $_instance = null;
    protected function __construct() {}
    protected function __clone() {}
    public function getInstance() {
        if (self::$_instance === null) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
}
class B extends A {
    protected static $_instance = null;
}
$a = A::getInstance();
$b = B::getInstance();
var_dump($a === $b); // bool(true) —— 子類共享了父類實例!

原因:self 在類定義時綁定,繼承類調用父類方法時 self::$_instance 仍指向父類屬性。

PHP 5.3+ 解決方案:後期靜態綁定 (LSB)

將 self 替換為 static,引用在運行時解析:

class C {
    protected static $_instance = null;
    protected function __construct() {}
    protected function __clone() {}
    public function getInstance() {
        if (static::$_instance === null) {
            static::$_instance = new static; // 關鍵:new static 而非 new self
        }
        return static::$_instance;
    }
}
class D extends C {
    protected static $_instance = null; // 必須重新聲明,隔離存儲
}
$c = C::getInstance();
$d = D::getInstance();
var_dump($c === $d); // bool(false) —— 完美隔離

關鍵點總結

  1. 構造函數、克隆方法設為 protected 防止外部實例化/克隆。
  2. 靜態屬性 $_instance 在每個具體單例類中**必須重新聲明**,否則仍會共享。
  3. 使用 static::$_instance 和 new static 實現 LSB。
  4. 僅適用 PHP 5.3+;舊版本需為每個類單獨寫 getInstance。

避坑提醒

  • PHP 單例無 Java 線程安全問題,但**有狀態類**慎用,單例生命周期貫穿整個請求,會增加內存佔用。
  • 單例模式屬於「反模式」爭議較大,建議優先考慮依賴注入容器管理對象生命周期。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved