Этот вопрос проверяет знание классической реализации шаблона Одиночка и понимание ее особенностей в PHP.
Singleton реализуется путем создания класса, который: 1) объявляет приватное статическое свойство для хранения единственного экземпляра; 2) имеет приватный конструктор, чтобы запретить создание объектов через new; 3) имеет публичный статический метод (часто getInstance()), который создает экземпляр (если он еще не создан) и возвращает его. В многопоточных средах нужно добавлять синхронизацию, но в PHP это обычно не требуется.
Реализация Singleton гарантирует, что у класса будет только один экземпляр во время выполнения скрипта.
class DatabaseConnection
{
// 1. Приватное статическое свойство для хранения экземпляра
private static ?self $instance = null;
// 2. Приватный конструктор для блокировки создания через new
private function __construct()
{
// Инициализация подключения (например, PDO)
}
// 3. Публичный статический метод для получения экземпляра
public static function getInstance(): self
{
// Если экземпляр еще не создан, создаем его
if (self::$instance === null) {
self::$instance = new self();
}
// Возвращаем существующий экземпляр
return self::$instance;
}
// 4. [Важно] Запрещаем клонирование объекта
public function __clone()
{
throw new \Exception("Cannot clone a singleton.");
}
// 5. [Важно] Запрещаем десериализацию
public function __wakeup()
{
throw new \Exception("Cannot unserialize a singleton.");
}
// ... остальные методы класса (например, query() и т.д.)
}
// Использование:
$db1 = DatabaseConnection::getInstance();
$db2 = DatabaseConnection::getInstance();
var_dump($db1 === $db2); // Выведет bool(true) - это один и тот же объектПриватный конструктор: Не позволяет создать экземпляр класса извне с помощью оператора new.
Статический метод getInstance: Контролирует жизненный цикл объекта. При первом вызове создает его, при последующих — возвращает уже существующий.
Запрет клонирования и десериализации: Эти операции могут создать копию объекта, нарушив принцип Singleton. Поэтому методы __clone и __wakeup должны быть объявлены приватными или вызывать исключение.
Вывод: Singleton — это простой, но мощный шаблон для управления единственным экземпляром ресурса. Однако его следует использовать с осторожностью, так как он по сути является глобальной переменной, что может затруднить модульное тестирование и сделать код связанным. Вместо "голого" Singleton в современных фреймворках часто используют контейнер внедрения зависимостей (DI Container), который может управлять жизненным циклом объектов как "одиночек" в более контролируемом виде.