Ответ
В своей практике на PHP я чаще всего применяю следующие паттерны:
1. Singleton (Одиночка) Использовал для глобального доступа к конфигурации или подключению к базе данных, чтобы избежать множественных инстансов.
class DatabaseConnection {
private static ?self $instance = null;
private function __construct() { /* ... */ }
private function __clone() {}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
// Использование
$db = DatabaseConnection::getInstance();
2. Factory (Фабрика) Применял для создания семейства связанных объектов, например, разных типов уведомлений (Email, SMS, Push).
interface Notification {
public function send(string $message): void;
}
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException('Unknown notification type')
};
}
}
3. Strategy (Стратегия) Использовал для инкапсуляции различных алгоритмов сортировки или способов оплаты (CreditCard, PayPal), которые можно подменять в рантайме.
interface PaymentStrategy {
public function pay(float $amount): bool;
}
class Order {
private PaymentStrategy $paymentStrategy;
public function setPaymentStrategy(PaymentStrategy $strategy): void {
$this->paymentStrategy = $strategy;
}
public function processPayment(float $amount): bool {
return $this->paymentStrategy->pay($amount);
}
}
4. Repository (Репозиторий) Активно применяю в Laravel-проектах для абстракции доступа к данным, что упрощает тестирование и смену источника данных.
// AppRepositoriesUserRepository.php
class UserRepository {
public function findById(int $id): ?User {
return User::find($id);
}
public function getAllActive(): Collection {
return User::where('is_active', true)->get();
}
}
Также сталкивался и применял Observer (для событийной модели), Decorator (для расширения функциональности) и Adapter (для интеграции со сторонними API).
Ответ 18+ 🔞
А, паттерны, говоришь? Ну, это ж как инструменты в гараже — одни нужны постоянно, другие лежат на всякий пожарный, а третьи вообще хер поймёшь, зачем нужны, пока в конкретную жопу не влезешь. Расскажу, с чем чаще всего вожусь, а то сидишь тут, подозрение ебать чувствую, что думаешь, будто я только на костылях из глобальных переменных и пишу.
1. Singleton (Одиночка) Этот, бля, как тот одинокий стул на кухне — все им пользуются, но больше одного на всю квартиру не надо. Я его обычно для подключения к базе юзаю, чтобы не плодить сущностей, а то приложение жрёт память, как не в себя. Смотри, как просто:
class DatabaseConnection {
private static ?self $instance = null;
private function __construct() { /* ... */ }
private function __clone() {}
public static function getInstance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
// Использование
$db = DatabaseConnection::getInstance();
Главное — конструктор приватный, чтобы какой-нибудь распиздяй не начал новые инстансы плодить. Один на весь проект и всё, доверия ебать ноль ко всем остальным.
2. Factory (Фабрика)
Ну, это когда тебе нужно что-то создать, но заранее хрен знает что именно. Типа, приходят уведомления: то письмо, то смс, то ещё какая мартышлюшка. Вместо того чтобы везде if-ами мозги выносить, заводишь фабрику — она тебе нужную хрень и склепает.
interface Notification {
public function send(string $message): void;
}
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException('Unknown notification type')
};
}
}
Красота же! Пришёл тип 'sms' — получи объект для смсок. Пришла хуйня — получи исключение в морду. Всё честно.
3. Strategy (Стратегия)
Вот это, бля, мощная штука. Представь, у тебя есть заказ и куча способов оплаты: картой, через PayPal, криптой ещё, ёпта. Можно, конечно, нагородить switch на пол-экрана, а можно сделать по-человечески. Стратегия — это когда ты выносишь каждый алгоритм в отдельный класс, а потом подсовываешь его основному объекту, как патрон в ствол.
interface PaymentStrategy {
public function pay(float $amount): bool;
}
class Order {
private PaymentStrategy $paymentStrategy;
public function setPaymentStrategy(PaymentStrategy $strategy): void {
$this->paymentStrategy = $strategy;
}
public function processPayment(float $amount): bool {
return $this->paymentStrategy->pay($amount);
}
}
Захотел сменить платёжку — просто подсунул другую стратегию. Удивление пиздец, как сразу жить проще становится.
4. Repository (Репозиторий) Особенно в Laravel'е это прям святое. Вместо того чтобы тыкать запросы к базе по всему коду, как слепой кот, ты собираешь их в одном месте — в репозитории. Тестировать в разы легче, да и если завтра базу поменять, не придётся пол-проекта переписывать.
// AppRepositoriesUserRepository.php
class UserRepository {
public function findById(int $id): ?User {
return User::find($id);
}
public function getAllActive(): Collection {
return User::where('is_active', true)->get();
}
}
Выглядит просто, но, бля, сколько нервов экономит. Это как иметь отдельный ящик для всех отвёрток, а не искать их по всему полу.
Ну и ещё, конечно, всякое бывало: Observer для событий (типа, "эй, все, кто подписался, вот вам уведомление!"), Decorator, чтобы обернуть функциональность, как луковицу, и Adapter, когда нужно впихнуть невпихуемое — старый кривой API заставить работать с твоей красивой системой. В общем, инструментов овердохуища, главное — понимать, какой и когда в руки брать, а не тыкать всем подряд, как полупидор.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶