Сайт вебмастера

Шаблон Singleton. Трейты (trait) в PHP

04-07-2019Время чтения ~ 3 мин.PHP/ООП 8866

Singleton (Одиночка) наверное самый известный в PHP паттерн. Я уже как-то писал о нём, но сейчас речь пойдёт уже с точки зрения ООП и практического использования.

Синглтон очень часто называют антипаттерном, который выражается в «неуместном использовании». На самом деле это действительно так: из-за своей простоты Singleton очень часто применяют там, где в общем-то он и не нужен.

Основное назначение Singleton в том, чтобы гарантировать только один экземпляр класса. ООП в PHP 5 был не так развит и ещё не было автозагрузки файлов, синглтон был оправдан для создания глобального объекта всего приложения, как например в CodeIgniter — $CI. Этот объект обслуживает все подключения файлов, библиотеки и т.п. Всё это создаёт очень жесткую структуру.

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

Где же тогда можно применять Singleton? В первую очередь это должно быть точечное использование ровно там, где это действительно нужно. Например есть класс, который реализует поддержку хуков (hooks). Поскольку этот объект должен быть единственным во всём приложении, то вполне логично сделать его синглтоном.

Или подключение к базам данных, где должны храниться все коннекты используемых баз, тоже логично сделать как Singleton.

В отличие от других шаблонов, Singleton применяется к самому классу и никак не связан с наследованием или композицией. Поэтому обычно весь код паттерна прописывают прямо в теле класса. И, чтобы этого не делать, в PHP можно использовать трейты (trait).

Trait

Вообще в ООП трейты («Типаж») представляет собой абстрактный тип данных, довольно близкий по своей сути к абстрактному классу. Главное отличие в том, что нельзя создать (наследовать) объект трейта, а также в том, что трейт может содержать только методы.

Но в PHP «трейты» на самом деле не трейты, а примеси, которые похожи, но уже позволяют содержать методы и поля. PHP-трейты очень часто сравнивают с аналогом copy-paste для классов, поскольку позволяют отделить повторяющийся код. Ну и ко всему прочему, именно с помощью трейтов в PHP можно реализовать множественное наследование.

Я не зря привёл много ссылок, чтобы вы с ними ознакомились, после того, как прочтете статью. :) Но суть в том, что трейты (дальше речь о php-трейтах) можно использовать именно как copy-paste для использования Singleton.

Реализация Singleton

Исходный код Singleton как обычно на гитхабе.

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

class MyClass
{
     use \Pattern\SingletonTrait; 
     ...
}
 
$m = MyClass::getInstance();
$m->...

Если попытаться создать MyClass с помощью new

$m = new MyClass();

выскочить php-ошибка (Error: Call to private MyClass::__construct()) — так создавать класс синглтона запрещено (потому что приватный конструктор). Также не получится его клонировать.

Похожие записи