Перейти к основному содержимому

Что это такое

Паттерн Одиночка (Singleton) гарантирует, что у класса есть ровно один экземпляр во всей программе, и даёт всем одну и ту же точку доступа к нему. Типичные одиночки: конфигурация, пул соединений, логгер.

Инструмент PHP для этого — приватный конструктор плюс статический метод instance(): никто вне класса не может вызвать new, а единственная точка доступа создаёт экземпляр при первом вызове. Поскольку PHP выполняет каждый запрос в отдельном изолированном процессе, «один на всю программу» означает один на запрос — или один на запуск скрипта командной строки.


Пример: одна конфигурация для всех

Конфигурация загружается при первом вызове Config::instance() и больше никогда. Каждый вызывающий получает один и тот же объект.

Загрузка один раз за приватным конструктором

Строка «загружаем конфигурацию» печатается только один раз, хотя instance() вызывается дважды, — а $a === $b доказывает, что оба вызывающих держат один и тот же экземпляр. Оператор ??= создаёт объект только тогда, когда свойство всё ещё равно null.

Prompt
Напишите PHP-скрипт с одиночкой Config: приватный конструктор, который печатает строку во время загрузки, приватное статическое свойство instance и публичный статический метод instance(), создающий объект только при первом вызове с помощью оператора ??=. Вызовите instance() дважды, напечатайте имя приложения и докажите сравнением на идентичность, что оба вызова возвращают один и тот же объект.
Вывод: PHP-скрипт

Когда его применять

Применяйте, когда чего-то действительно должно быть ровно одно: одна загруженная конфигурация, один пул соединений, один кэш — и когда создание дорого или дубликаты будут конфликтовать.

Откажитесь, когда значение можно просто создать в начале скрипта и передать тем, кому оно нужно. Открытая передача зависимостей понятнее глобального доступа — одиночка это последнее средство, а не первое.


Плюсы и минусы

Плюсы: гарантированно единственный экземпляр — приватный конструктор блокирует любой посторонний new; ленивое создание при первом использовании; одна очевидная точка доступа.

Минусы: это замаскированная глобальная переменная — скрытые зависимости усложняют чтение кода; тесты не могут легко подменить его заглушкой; чрезмерное применение ведёт к запутанным программам.