Новый взгляд на старый Singleton.

Шаблон проектирования Singleton (одиночка) это основа, с него начинается изучение паттернов, потому что он самый простой в понимании, и в целом описывает суть шаблонов.

class Product {
    private static $instance;  
    
    public static function getInstance() { 
        if ( empty(self::$instance) ) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    private function __construct(){}  
    private function __clone()    {} 
    private function __wakeup()   {}  
}

Принято, что в Singleton присутствует статический метод под названием getInstance(), поэтому если в коде встретится getInstance() , — знайте, перед вами на 99,9 % Singleton и не имеет значение, что сам класс называется не Singleton, а к примеру Product.

Основная магия происходит в нем, а именно, метод getInstance() проверяет статическое свойство $instance, если оно пустое, значит создает объект с помощью конструкции new self() и помещает его в $instance. В противном случае возвращает то самое $instance с объектом в нем. Вариантов реализации getInstance() вы встретите много, но все они сводятся к одному.

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

Еще один:

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

и еще …

public static function getInstance()
    {
        if (!(self::$instance instanceof self)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

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

$firstProduct = Product::getInstance();
$secondProduct = Product::getInstance();
var_dump($firstProduct); // object(Product)#1 (0) { }
var_dump($secondProduct); // object(Product)#1 (0) { }

Для проверки создания объектов мы используем var_dump, а не привычное print_r, что бы увидеть созданный объект и его порядковый номер.

Конечно, нам надо обезопасить свой Singleton и закрыть все возможности создания объекта в обход new self(). Сделать это можно с помощью пустых «магических» методов __construct(), __clone() и __wakeup().

Почему статический метод, а не обычный в Singleton?

Статический метод принадлежит классу, а не объекту, то есть для его вызова нам не надо создавать объект, поэтому это дополнительная гарантия, что при вызове getInstance() не будет создан новый объект.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *