В ИТ все любят умничать словами «шаблоны проектирования». Читаешь книжки — ощущение, что без них твой код вообще не имеет права жить. Но правда в том, что шаблоны — это как набор старых инструментов в гараже. Иногда достаёшь и пользуешься, а иногда понимаешь, что проще было бы забить гвоздь молотком, а не разбирать перфоратор.
Возьмём три простых зверя: Singleton, Factory и Observer. Они встречаются почти в каждом PHP-проекте, даже если ты не хотел. Да, и даже если ты считаешь себя выше этого.
Singleton
О, старина Singleton. Самый задроченный шаблон. Его задача — гарантировать, что в приложении есть ровно один объект этого класса. Всё. Никакой магии.
Где реально нужен:
- подключение к базе (PDO, mysqli — не важно, один коннект рулит),
- глобальные настройки,
- иногда кэш или логгер.
Где не нужен:
- везде остальное. Потому что потом код начинает выглядеть так, будто у тебя глобальная переменная воскресла и пошла пить твою кровь.
Пример (минимум кода, максимум смысла):
class DB {
private static $instance;
private function __construct() {}
public static function getInstance() {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
// Использование $db = DB::getInstance();
Всё. Если ты начинаешь городить к этому 200 строк с двойными блокировками и прочей хернёй — проверь, не пишешь ли ты случайно Java.
Factory
Factory — это когда тебе надо создавать объекты, но не хочется в каждом месте писать new Dog(), new Cat(), new Whatever(). Вместо этого ты прячешь эту грязь за фабрикой.
Пример из жизни: у тебя есть сервис по работе с платёжками, и разные провайдеры. Где-то Yookassa, где-то Stripe. Код клиента должен просто сказать: «Дай мне платёжку», а не знать про все эти кишки.
interface Animal {
public function speak();
}
class Dog implements Animal {
public function speak() { return "Гав"; }
}
class Cat implements Animal {
public function speak() { return "Мяу"; }
}
class AnimalFactory {
public static function create($type) {
switch ($type) {
case 'dog': return new Dog();
case 'cat': return new Cat();
default: throw new Exception("Животное не найдено");
}
}
}
// Использование $animal = AnimalFactory::create('dog');
echo $animal->speak(); // "Гав" Фабрика полезна, когда у тебя один интерфейс, куча реализаций, и ты не хочешь, чтобы твой код знал об этом зоопарке.
Observer
Observer — это паттерн «я крикнул, все услышали». У тебя есть объект (Subject), и куча подписчиков (Observers), которые ждут, что он изменится.
Примеры:
- Laravel Events (всё на Observer),
- отправка писем после регистрации,
- реакция на обновление данных (например, пользователь сменил пароль — пушнули событие).
Минимальный пример:
class Subject {
private $observers = [];
private $state;
public function attach($observer) {
$this->observers[] = $observer;
}
public function setState($state) {
$this->state = $state;
$this->notify();
}
public function getState() {
return $this->state;
}
private function notify() {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}
interface Observer {
public function update(Subject $subject);
}
class Logger implements Observer {
public function update(Subject $subject) {
echo "Состояние изменилось: " . $subject->getState() . "\n";
}
}
// Использование $subject = new Subject();
$subject->attach(new Logger());
$subject->setState("active"); // "Состояние изменилось: active" Да, это звучит как лишняя абстракция, но когда у тебя 5+ реакций на одно событие, Observer реально спасает от кучи хардкода.
Вместо вывода
Все эти паттерны — это не законы природы. Это просто старые костыли, которые помогают не утонуть в бардаке.
- Singleton — хорош, пока не превращается в глобальные переменные с короной.
- Factory — экономит твои нервы, когда в проекте больше одного типа сущностей.
- Observer — норм штука, если хочешь, чтобы объекты разговаривали между собой без прямых связей.
Не надо молиться на паттерны, но и игнорировать их тоже тупо. Просто используй их как молоток, а не как религию.
0 комментариев