← Назад к вопросам
Что нужно для реализации Singleton помимо приватного конструктора?
1.7 Middle🔥 111 комментариев
#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Singleton: реализация
Singleton — это паттерн, который гарантирует, что класс имеет только один экземпляр, и предоставляет глобальный доступ к этому экземпляру.
Необходимые элементы
class Singleton {
// 1. Приватный конструктор
private function __construct() {}
// 2. Статическое свойство для хранения экземпляра
private static ?Singleton $instance = null;
// 3. Статический метод getInstance()
public static function getInstance(): Singleton {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
// 4. Приватный clone (запретить клонирование)
private function __clone() {}
// 5. Приватный wakeup (запретить десериализацию)
private function __wakeup() {}
}
Использование
$singleton1 = Singleton::getInstance();
$singleton2 = Singleton::getInstance();
var_dump($singleton1 === $singleton2); // true (один и тот же объект)
Зачем все эти части?
// 1. Приватный конструктор
private function __construct() {}
// Запрещает: $obj = new Singleton(); // Error!
// 2. Статическое свойство
private static ?Singleton $instance = null;
// Хранит единственный экземпляр класса
// 3. getInstance() метод
public static function getInstance(): Singleton {}
// Возвращает единственный экземпляр
// 4. Приватный __clone()
private function __clone() {}
// Запрещает: $copy = clone $singleton; // Error!
// 5. Приватный __wakeup()
private function __wakeup() {}
// Запрещает: $obj = unserialize($data); // Error!
Практический пример
class Database {
private static ?self $instance = null;
private $connection;
private function __construct() {
$this->connection = new PDO('...');
}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query($sql) {
return $this->connection->query($sql);
}
private function __clone() {}
private function __wakeup() {}
}
// Везде одна и та же БД-соединение
$db1 = Database::getInstance();
$db2 = Database::getInstance();
// $db1 === $db2 (true)
Lazy initialization
class Singleton {
private static ?self $instance = null;
// Создаётся только при первом вызове getInstance()
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
// Инициализация
}
return self::$instance;
}
}
Есть ли лучше решение?
Да! В modern PHP используй Dependency Injection вместо Singleton:
// Вместо Singleton
$db = Database::getInstance();
// Лучше: DI контейнер
container()->bind(Database::class, function() {
return new Database();
});
// Инъектируй в конструктор
class UserService {
public function __construct(private Database $db) {}
}
Вывод
Singleton требует: приватный конструктор, статическое свойство для хранения, getInstance() метод, запрет на clone и deserialize. Но в modern приложениях лучше использовать DI контейнеры.