流苏小筑

PHP与设计模式:单例模式详解与实战

PHP 单例模式详解与实战

单例模式(Singleton Pattern)是软件设计中的一种常用模式,它确保一个类在整个应用中只有一个实例,同时提供全局访问点。单例模式广泛应用于日志记录、数据库连接、配置管理等场景。


1. 单例模式简介


2. 单例模式的实现步骤

  1. 私有化构造函数:防止外部通过 new 创建实例。
  2. 私有化克隆方法:禁止对象被克隆。
  3. 创建静态属性存储实例:用于保存类的唯一实例。
  4. 提供静态方法获取实例:确保实例的唯一性。

3. PHP 单例模式实现

以下是单例模式的完整代码示例:

<?php

class Singleton {
    // 静态属性,存放唯一实例
    private static $instance = null;

    // 私有化构造函数,禁止外部实例化
    private function __construct() {
        echo "Instance created." . PHP_EOL;
    }

    // 禁止克隆对象
    private function __clone() {}

    // 禁止反序列化
    private function __wakeup() {}

    // 静态方法,提供全局访问点
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

// 测试单例模式
$instance1 = Singleton::getInstance(); // 输出: Instance created.
$instance2 = Singleton::getInstance();

var_dump($instance1 === $instance2); // 输出: bool(true)
?>

4.代码解析

private static $instance

用于存储单例对象。初始值为 null。
private function __construct()

将构造函数私有化,阻止外部直接创建对象。
public static function getInstance()

静态方法,负责检查并创建实例。如果实例不存在(null),则创建实例;否则返回已有实例。
private function __clone() 和 private function __wakeup()

分别禁止克隆和反序列化,确保实例唯一性。


5. 单例模式的应用场景

  1. 数据库连接
    数据库连接通常只需要一个实例,使用单例模式可以避免重复创建连接。

    <?php
    
    class Database {
     private static $instance = null;
     private $connection;
    
     private function __construct() {
         // 创建数据库连接
         $this->connection = new PDO('mysql:host=localhost;dbname=test', 'root', '');
     }
    
     public static function getInstance() {
         if (self::$instance === null) {
             self::$instance = new self();
         }
         return self::$instance;
     }
    
     public function getConnection() {
         return $this->connection;
     }
    }
    
    // 测试
    $db1 = Database::getInstance()->getConnection();
    $db2 = Database::getInstance()->getConnection();
    
    var_dump($db1 === $db2); // 输出: bool(true)
    ?>
  2. 配置管理
    在项目中,配置通常是全局共享的,使用单例模式可以确保配置管理的一致性。

    <?php
    
    class Config {
     private static $instance = null;
     private $settings = [];
    
     private function __construct() {}
    
     public static function getInstance() {
         if (self::$instance === null) {
             self::$instance = new self();
         }
         return self::$instance;
     }
    
     public function set($key, $value) {
         $this->settings[$key] = $value;
     }
    
     public function get($key) {
         return $this->settings[$key] ?? null;
     }
    }
    
    // 测试
    $config = Config::getInstance();
    $config->set('app_name', 'My Application');
    echo $config->get('app_name'); // 输出: My Application
    ?>
  3. 日志记录
    日志记录器需要全局访问,但避免多次实例化。

    <?php
    
    class Logger {
     private static $instance = null;
    
     private function __construct() {}
    
     public static function getInstance() {
         if (self::$instance === null) {
             self::$instance = new self();
         }
         return self::$instance;
     }
    
     public function log($message) {
         echo "[LOG]: $message" . PHP_EOL;
     }
    }
    
    // 测试
    Logger::getInstance()->log('This is a log message.');
    Logger::getInstance()->log('This is another log message.');
    ?>

6. 单例模式的优缺点


7. 多线程环境中的单例

在多线程环境下,单例模式需要通过加锁机制确保线程安全:

<?php

class ThreadSafeSingleton {
    private static $instance = null;
    private static $lock = false;

    private function __construct() {}

    public static function getInstance() {
        if (self::$instance === null) {
            // 加锁,确保线程安全
            if (!self::$lock) {
                self::$lock = true;
                self::$instance = new self();
                self::$lock = false;
            }
        }
        return self::$instance;
    }
}
?>

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »