本文目录导读:

- 经典单例模式(最常用)
- Trait方式(可复用)
- 延迟加载 + 线程安全
- 注册表模式(Registry Pattern)
- 实现全局静态类(final + private constructor)
- 推荐的最佳实践方案
- 使用建议
在PHP项目中实现单例模式的全局类,有多种方式,我为你整理了几种常见的实现方案:
经典单例模式(最常用)
<?php
class Database
{
private static ?Database $instance = null;
// 私有构造函数,防止外部实例化
private function __construct()
{
// 初始化数据库连接等
echo "创建数据库连接";
}
// 私有克隆方法,防止克隆
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)
{
echo "执行查询: {$sql}";
}
}
// 使用示例
$db = Database::getInstance();
$db->query("SELECT * FROM users");
$db2 = Database::getInstance();
var_dump($db === $db2); // true,同一个实例
Trait方式(可复用)
<?php
trait Singleton
{
private static ?self $instance = null;
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;
}
}
// 使用Trait实现单例
class Logger
{
use Singleton;
public function log(string $message)
{
echo "[LOG]: {$message}\n";
}
}
class Config
{
use Singleton;
private array $settings = [];
public function set(string $key, $value): void
{
$this->settings[$key] = $value;
}
public function get(string $key)
{
return $this->settings[$key] ?? null;
}
}
// 使用示例
$logger = Logger::getInstance();
$logger->log("系统启动");
$config = Config::getInstance();
$config->set("db_host", "localhost");
echo $config->get("db_host"); // localhost
延迟加载 + 线程安全
<?php
class CacheManager
{
private static ?CacheManager $instance = null;
private static array $locks = [];
private function __construct()
{
// 初始化缓存
}
private function __clone() {}
public static function getInstance(): self
{
// 双重检查锁定(Double-Checked Locking)
if (self::$instance === null) {
// 使用文件锁或数据库锁确保线程安全
$lock = fopen(__FILE__ . '.lock', 'w');
if (flock($lock, LOCK_EX)) {
if (self::$instance === null) {
self::$instance = new self();
}
flock($lock, LOCK_UN);
}
fclose($lock);
}
return self::$instance;
}
public function get(string $key): mixed
{
return "缓存数据: {$key}";
}
}
注册表模式(Registry Pattern)
<?php
class Registry
{
private static array $instances = [];
// 注册一个单例
public static function set(string $key, object $instance): void
{
self::$instances[$key] = $instance;
}
// 获取一个单例
public static function get(string $key): ?object
{
return self::$instances[$key] ?? null;
}
// 检查是否已注册
public static function has(string $key): bool
{
return isset(self::$instances[$key]);
}
// 移除注册
public static function remove(string $key): void
{
unset(self::$instances[$key]);
}
}
// 使用注册表管理单例
class UserService
{
public function getUsers(): array
{
return ['user1', 'user2'];
}
}
// 注册单例
Registry::set('userService', new UserService());
// 获取单例
$userService = Registry::get('userService');
print_r($userService->getUsers());
// 判断是否已注册
if (Registry::has('userService')) {
echo "UserService 已注册";
}
实现全局静态类(final + private constructor)
<?php
final class GlobalApp
{
private static array $data = [];
// 私有构造函数,防止实例化
private function __construct() {}
// 静态方法实现全局访问
public static function set(string $key, $value): void
{
self::$data[$key] = $value;
}
public static function get(string $key): mixed
{
return self::$data[$key] ?? null;
}
public static function has(string $key): bool
{
return isset(self::$data[$key]);
}
public static function all(): array
{
return self::$data;
}
}
// 使用示例(类似全局变量)
GlobalApp::set('app_name', 'My PHP App');
GlobalApp::set('version', '1.0.0');
echo GlobalApp::get('app_name'); // My PHP App
print_r(GlobalApp::all());
推荐的最佳实践方案
<?php
/**
* 完整的单例基类
*/
abstract class SingletonBase
{
protected static array $instances = [];
// 禁止外部实例化
protected function __construct()
{
$this->init();
}
// 子类可以重写此方法进行初始化
protected function init(): void {}
// 禁止克隆
protected function __clone() {}
// 禁止反序列化
public function __wakeup(): void
{
throw new \Exception("Cannot unserialize singleton");
}
// 获取实例
final public static function getInstance(): static
{
$class = static::class;
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new static();
}
return self::$instances[$class];
}
// 重置实例(用于测试)
final public static function resetInstance(): void
{
$class = static::class;
unset(self::$instances[$class]);
}
}
// 实际使用
class AppConfig extends SingletonBase
{
private array $config = [];
protected function init(): void
{
// 加载配置文件
$this->config = [
'db_host' => 'localhost',
'db_name' => 'myapp',
'debug' => true
];
}
public function get(string $key, $default = null): mixed
{
return $this->config[$key] ?? $default;
}
}
class AppLogger extends SingletonBase
{
private string $logFile;
protected function init(): void
{
$this->logFile = '/var/log/app.log';
}
public function log(string $message): void
{
$timestamp = date('Y-m-d H:i:s');
file_put_contents(
$this->logFile,
"[{$timestamp}] {$message}\n",
FILE_APPEND
);
}
}
// 使用示例
$config = AppConfig::getInstance();
echo $config->get('db_host'); // localhost
$logger = AppLogger::getInstance();
$logger->log("应用启动");
// 验证单例
$config2 = AppConfig::getInstance();
var_dump($config === $config2); // true
使用建议
-
选择合适的方案:
- 小型项目:使用经典单例模式
- 大型项目:使用继承或Trait方式
- 需要管理多个单例:使用注册表模式
-
注意线程安全:
- PHP-FPM模式下不需要担心
- CLI模式下可能需要考虑
-
测试友好:
- 提供
resetInstance()方法用于测试 - 考虑使用依赖注入容器替代单例
- 提供
-
避免滥用:
- 单例模式会增加耦合
- 只在确实需要全局唯一实例时使用
选择哪种方式取决于你的具体需求和项目规模,我个人推荐使用Trait或继承方式,这样可以保持代码的整洁和可维护性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播