Шаблоны проектирования на PHP
Одиночка (Singleton), порождающий
Гарантирует создание одного экземпляра класса.
class Application
{
private static $oInstance; // переменная для хренения экземпляра
public static function getInstance(): self
{
if (!isset(static::$oInstance)) { // проверяем существование экземпляра (состояния)
self::$oInstance = new self(); // если его не было, создаем его
}
return self::$oInstance; // возвращаем новое или имеющийся экземпляр
}
}
var_dump(Application::getInstance()); // object(Application)#1 (0) {}
var_dump(Application::getInstance()); // object(Application)#1 (0) {}
Простая фабрика (Simple Factory), порождающий
Инкапсуляция создания объекта.
interface Animal // Интерфейс - все животные должны уметь говорить
{
public function speak(); // издает звук
}
class Cat implements Animal // Кошка
{
public function speak()
{
echo 'Мяу!';
}
}
class Dog implements Animal // Собака
{
public function speak()
{
echo 'Гав!';
}
}
class AnimalFactory // Простая фабрика
{
public function create($type) // Единственный метод - создает животных
{
if ($type === 'cat') {
return new Cat();
} elseif ($type === 'dog') {
return new Dog();
}
}
}
// Использование
$factory = new AnimalFactory();
$cat = $factory->create('cat')->speak(); // Мяу!
$dog = $factory->create('dog')->speak(); // Гав!
Фасад (Facade), структурный
Предоставляет простой интерфейс к сложной системе классов.
class DatabaseBackup
{
public function dumpDatabase(string $sDbName) {} // создание дампа бд
public function compressDump() {} // сжатие дампа
}
class FileSystemBackup
{
public function scanFiles(string $sDirectory) {} // листинг файлов
public function archiveFiles(array $aFiles) {} // архивирование файлов
}
class CloudStorage
{
public function upload(string $sFilename) {} // выгрузка файла
public function checkSpace() {} // проверка места
}
class BackupLogger
{
public function log(string $sMessage) {} // вывод лога
}
class BackupFacade
{
private $oDbBackup;
private $oFsBackup;
private $oCloud;
private $oLogger;
public function __construct()
{
$this->oDbBackup = new DatabaseBackup();
$this->oFsBackup = new FileSystemBackup();
$this->oCloud = new CloudStorage();
$this->oLogger = new BackupLogger();
}
// полная процедура всех видов бекапов
public function createFullBackup(string $sProjectDir, string $sDbName) {}
}
// Использование
$oBackup = new BackupFacade();
$oBackup->createFullBackup("/var/www/project", "myapp_db");
Наблюдатель (Observer), поведенческий
Создание механизма подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах..
interface EventListener // интерфейс для всех слушателей событий
{
public function handle($event); // класс-слушатель должен реализовать этот метод
}
class EventDispatcher // класс диспетчера событий
{
private array $aListeners = []; // массив для хранения слушателей
// метод для регистрации слушателя на определенное событие
public function addListener($sEventName, EventListener $oListener)
{
$this->aListeners[$sEventName][] = $oListener;
}
public function dispatch($sEventName, $mData) // запуск событий
{
foreach ($this->aListeners[$sEventName] as $oListener) {
$oListener->handle($mData);
}
}
}
class LoggerListener implements EventListener // слушатель для логирования событий
{
public function handle($mEvent) {}
}
class EmailNotifierListener implements EventListener // слушатель для отправки email-уведомлений
{
public function handle($mEvent) {}
}
// Использование
$oDispatcher = new EventDispatcher(); // Создаем экземпляр диспетчера событий
$oLogger = new LoggerListener(); // Слушатель для логирования
$oNotifier = new EmailNotifierListener(); // Слушатель для email-уведомлений
// Подписываем слушателей на событие 'user.registered'
$oDispatcher->addListener('user.registered', $oLogger);
$oDispatcher->addListener('user.registered', $oNotifier);
// Запускаем событие 'user.registered' с данными о пользователе
// Все подписанные слушатели получат эти данные
$oDispatcher->dispatch('user.registered', ['name' => 'Иван']);
Стратегия (Strategy), поведенческий
Определяет семейство схожих алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость.
interface IExportStrategy // Интерфейс стратегии экспорта данных.
{
public function export(array $aData);
}
class CJsonExport implements IExportStrategy
{
public function export(array $aData) {} // Экспортирует данные в JSON формат.
}
class CXmlExport implements IExportStrategy
{
public function export(array $aData) {} // Экспортирует данные в XML формат.
}
class CCsvExport implements IExportStrategy
{
public function export(array $aData) {} //Экспортирует данные в CSV формат.
}
// Пример использования паттерна Стратегия
$aData = ['name' => 'John', 'age' => 30]; // a - array (массив данных)
$oExporter = new CJsonExport(); // o - object (объект экспортера)
echo $oExporter->export($aData);
Адаптер (Adapter), структурный
Позволяет объектам с несовместимыми интерфейсами работать вместе.
// Целевой интерфейс
interface INotification
{
public function send(string $sMessage); // Отправляет уведомление
}
// Адаптируемые классы (разные сервисы)
class CEmailService
{
public function sendEmail(string $sTo, string $sText) {} // Отправляет email
}
class CSmsService
{
public function sendSms(string $sPhone, string $sMsg) {} // Отправляет SMS
}
// Адаптеры
class CEmailAdapter implements INotification
{
public function __construct(private CEmailService $oEmailService) {}
public function send(string $sMessage) // Адаптирует для email
{
return $this->oEmailService->sendEmail('user@test.com', $sMessage);
}
}
class CSmsAdapter implements INotification
{
public function __construct(private CSmsService $oSmsService) {}
public function send(string $sMessage) // Адаптирует для SMS
{
return $this->oSmsService->sendSms('+1234567890', $sMessage);
}
}
// Использование
$aNotifications = [
new CEmailAdapter(new CEmailService()),
new CSmsAdapter(new CSmsService())
];
foreach ($aNotifications as $oNotification) {
$oNotification->send("Hello world!"); // теперь у обеих сервисов один метод
}