php怎么实现单例模式
单例模式的基本概念
单例模式确保一个类只有一个实例,并提供一个全局访问点。适用于需要频繁创建和销毁的对象,或控制资源访问的场景(如数据库连接、日志管理等)。
PHP 单例模式的实现步骤
私有化构造函数
防止外部直接通过 new 创建实例。构造函数应声明为 private 或 protected。
private function __construct() {}
静态私有属性保存实例
用一个静态私有变量存储类的唯一实例。
private static $instance = null;
静态公共方法获取实例
通过静态方法提供全局访问点。如果实例不存在则创建,存在则直接返回。
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
防止克隆和反序列化
通过私有化 __clone() 和 __wakeup() 方法防止通过克隆或反序列化创建新实例。
private function __clone() {}
private function __wakeup() {}
完整代码示例
class Singleton {
private static $instance = null;
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
// 使用示例
$instance1 = Singleton::getInstance();
$instance2 = Singleton::getInstance();
var_dump($instance1 === $instance2); // 输出 true,说明是同一个实例
线程安全注意事项
PHP 本身是单线程的(SAPI 环境下),通常无需考虑多线程问题。但在多进程或特殊扩展(如 pthreads)中,需通过加锁(如 flock)确保原子性。
public static function getInstance() {
if (self::$instance === null) {
$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;
}
实际应用场景
- 数据库连接池管理
- 配置信息全局访问
- 日志记录器
避免滥用单例模式,过度使用会导致代码耦合度高,难以测试。







