PHP Singleton Design Pattern Порождающий паттерн

Паттерн Одиночка в PHP

Короткий скринкаст: паттерн «Одиночка» (Singleton) — один объект на всё приложение с ленивой инициализацией.

Singleton Pattern — открыть страницу урока

Описание

Мы делаем Logger, у которого не может быть больше одного экземпляра. Конструктор приватный, а getInstance() создаёт объект только при первом обращении и дальше всегда возвращает его же. Пишем сообщение через $a, читаем через $b — и это один и тот же объект.

UML-диаграмма

classDiagram class Logger { -static Logger instance +array messages -__construct() +static getInstance() Logger +log(message: string) void } Logger --> Logger : same

Код

Logger.php

class Logger
{
    private static ?Logger $instance = null;

    public array $messages = [];

    private function __construct() {}

    public static function getInstance(): Logger
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    public function log(string $message): void
    {
        $this->messages[] = $message;
    }
}

demo.php

require_once 'Logger.php';

$a = Logger::getInstance();
$b = Logger::getInstance();

$a->log('first');

echo $a === $b ? 'Same instance: true' : 'Same instance: false';
echo PHP_EOL;
echo 'Messages: ' . implode(', ', $b->messages);

Заметка: плюсы и критика

Преимущество — одна общая точка доступа и ленивое создание: экземпляр не занимает память, пока не понадобился. Но за это платим глобальным состоянием: кто угодно может писать в лог, что усложняет тесты и прячет зависимость. Во многих случаях между синглтоном и «просто инъекцией одного объекта в контейнере» стоит выбрать второе — тогда решение остаётся в руках вызывающего кода.

Пример результата

После php demo.php в терминале появится:

Same instance: true
Messages: first

Преимущества

  • Гарантирует единственный экземпляр на всё приложение.
  • Ленивая инициализация: объект создаётся при первом обращении.
  • Общая точка доступа к разделяемому ресурсу.
  • Экономит память и ресурсы: одно соединение, один логгер.

Когда использовать

  • Когда у класса должен быть ровно один экземпляр.
  • Когда нужен общий доступ к разделяемому ресурсу (конфиг, лог, кэш).
  • Когда создание ресурса дорого и его стоит делать лениво.
  • Когда важно контролировать глобальное состояние из одного места.

Использование в Laravel

В Laravel Одиночка — это сервис-контейнер: биндинг через ->singleton() гарантирует, что app() вернёт один и тот же объект. Менеджеры Illuminate\Log\LogManager, Illuminate\Cache\CacheManager и подключение к БД зарегистрированы как одиночки, а фасады (Illuminate\Support\Facades\Log, Cache) дают к ним статический доступ.