Что произойдет при повторном вызове метода getInstance() у Singleton?

Ответ

При повторном вызове getInstance() будет возвращен тот же самый экземпляр объекта, который был создан при первом вызове. Новый объект создан не будет. В этом и заключается основная цель паттерна Singleton — гарантировать существование только одного экземпляра класса.

Классическая реализация на PHP:

class DatabaseConnection
{
    // Статическая переменная для хранения единственного экземпляра.
    private static ?self $instance = null;

    // Приватный конструктор блокирует создание через 'new' извне класса.
    private function __construct()
    {
        // Инициализация подключения к БД...
        $this->connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }

    // Публичный статический метод для получения экземпляра.
    public static function getInstance(): self
    {
        // Проверка: если экземпляр еще не создан, создаем его.
        if (self::$instance === null) {
            self::$instance = new self();
        }
        // Все последующие вызовы вернут уже созданный экземпляр.
        return self::$instance;
    }

    // Другие полезные методы...
    public function getConnection(): PDO
    {
        return $this->connection;
    }
}

// Использование:
$db1 = DatabaseConnection::getInstance(); // Создается новый объект.
$db2 = DatabaseConnection::getInstance(); // Возвращается существующий объект ($db1).

var_dump($db1 === $db2); // bool(true) - это один и тот же объект.

Ключевые моменты:

  • Повторный вызов getInstance() не выполняет код new self(), так как условие self::$instance === null уже ложно.
  • Это обеспечивает глобальный доступ к одному ресурсу (например, подключению к БД, конфигурации, логгеру) без его дублирования в памяти.
  • Важно помнить о потенциальных проблемах Singleton, таких как скрытые зависимости и усложнение тестирования, поэтому его следует использовать обдуманно.

Ответ 18+ 🔞

Давай разберём этот ваш синглтон, а то народ путается, как будто на дворе 2002-й год. Представь, что у тебя есть класс, который должен существовать в единственном экземпляре, как последняя бутылка пива в холодильнике в три часа ночи. Вот за этим синглтон и нужен.

Так вот, когда ты второй раз вызываешь getInstance(), тебе возвращается тот же самый объект, который создался в первый раз. Новый не создаётся, блядь, ни под каким видом. В этом и есть весь смысл — чтобы объект был один, как нос на лице. Не два, не три, а один, ёпта.

Вот как это выглядит на PHP, если делать по-старинке:

class DatabaseConnection
{
    // Тут мы прячем наш единственный экземпляр. Пока тут null — нихуя нет.
    private static ?self $instance = null;

    // Конструктор приватный! Это чтобы какой-нибудь умник не сделал 'new DatabaseConnection()' снаружи.
    private function __construct()
    {
        // Тут обычно инициализация, типа подключения к базе.
        $this->connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    }

    // А вот этот метод — единственные ворота к нашему объекту.
    public static function getInstance(): self
    {
        // Смотри сюда. Если экземпляр ещё не создан (то есть null)...
        if (self::$instance === null) {
            // ...только тогда мы его создаём.
            self::$instance = new self();
        }
        // А если он уже есть, то просто возвращаем его, без всякого "new". Хуй с горы, понимаешь?
        return self::$instance;
    }

    // Ну и какие-то полезные методы, чтобы не просто так объект болтался.
    public function getConnection(): PDO
    {
        return $this->connection;
    }
}

// Используем:
$db1 = DatabaseConnection::getInstance(); // В этот момент создаётся новый объект.
$db2 = DatabaseConnection::getInstance(); // А тут уже возвращается старый, тот самый $db1.

var_dump($db1 === $db2); // Выведет bool(true) — это один и тот же объект, Карл!

Что тут важно уяснить, чтобы не быть манда с ушами:

  • На второй и все последующие вызовы getInstance() код new self() НЕ выполняется. Условие в if уже не проходит, потому что self::$instance больше не null. Всё, приехали. Возвращается то, что уже есть.
  • Вся фишка в том, чтобы дать глобальный доступ к какому-то ресурсу (типа того же подключения к базе), но чтобы этот ресурс не плодился, как кролики. Один раз создал — и пользуешься.
  • Но и ебаться с ним надо аккуратно. Этот паттерн — такая хитрая жопа. Он создаёт скрытые зависимости, и потом тестировать код — тот ещё пиздец. Поэтому юзать его надо с умом, а не просто потому что модно. Сам от себя охуеешь потом, когда начнёшь рефакторить.