← Назад к вопросам

Расскажите о паттернах проектирования GoF. Какие паттерны вы использовали на практике?

3.0 Senior🔥 192 комментариев
#Архитектура и паттерны#Опыт и карьера

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерны проектирования GoF: фундамент объектно-ориентированного дизайна

Паттерны проектирования GoF (Gang of Four) — это 23 классических шаблона, описанных в книге "Design Patterns: Elements of Reusable Object-Oriented Software" (1994). Они делятся на три категории:

1. Порождающие паттерны

Отвечают за создание объектов, скрывая логику инстанцирования:

  • Singleton (Одиночка) — гарантирует единственный экземпляр класса.
  • Factory Method (Фабричный метод) — определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
  • Abstract Factory (Абстрактная фабрика) — создаёт семейства связанных объектов.
  • Builder (Строитель) — отделяет конструирование сложного объекта от его представления.
  • Prototype (Прототип) — создаёт новые объекты копированием существующего прототипа.

2. Структурные паттерны

Организуют классы и объекты в более крупные структуры:

  • Adapter (Адаптер) — обеспечивает совместную работу несовместимых интерфейсов.
  • Decorator (Декоратор) — динамически добавляет объекту новые обязанности.
  • Proxy (Заместитель) — предоставляет суррогатный объект, контролирующий доступ к другому объекту.
  • Composite (Компоновщик) — объединяет объекты в древовидные структуры.
  • Facade (Фасад) — предоставляет унифицированный интерфейс к сложной системе.

3. Поведенческие паттерны

Определяют взаимодействие между объектами и распределение ответственности:

  • Strategy (Стратегия) — определяет семейство алгоритмов, инкапсулирует каждый и делает их взаимозаменяемыми.
  • Observer (Наблюдатель) — определяет зависимость "один-ко-многим" между объектами.
  • Command (Команда) — инкапсулирует запрос как объект.
  • Iterator (Итератор) — предоставляет способ последовательного доступа к элементам коллекции.
  • Chain of Responsibility (Цепочка обязанностей) — передаёт запрос по цепочке обработчиков.

Практический опыт применения паттернов

В моей практике как PHP-разработчика особенно часто применялись следующие паттерны:

Singleton для конфигурации и подключения к БД

class DatabaseConnection {
    private static $instance = null;
    private $connection;
    
    private function __construct() {
        $this->connection = new PDO(
            'mysql:host=localhost;dbname=test',
            'username',
            'password'
        );
    }
    
    public static function getInstance(): self {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function getConnection(): PDO {
        return $this->connection;
    }
}

// Использование
$db = DatabaseConnection::getInstance()->getConnection();

Factory Method для создания различных типов пользователей

interface User {
    public function getRole(): string;
}

class AdminUser implements User {
    public function getRole(): string {
        return 'admin';
    }
}

class CustomerUser implements User {
    public function getRole(): string {
        return 'customer';
    }
}

abstract class UserFactory {
    abstract public function createUser(): User;
    
    public function getUserInfo(): string {
        $user = $this->createUser();
        return "User role: " . $user->getRole();
    }
}

class AdminFactory extends UserFactory {
    public function createUser(): User {
        return new AdminUser();
    }
}

Strategy для реализации различных способов оплаты

interface PaymentStrategy {
    public function pay(float $amount): bool;
}

class CreditCardPayment implements PaymentStrategy {
    public function pay(float $amount): bool {
        // Логика оплаты кредитной картой
        return true;
    }
}

class PayPalPayment implements PaymentStrategy {
    public function pay(float $amount): bool {
        // Логика оплаты через PayPal
        return true;
    }
}

class PaymentContext {
    private PaymentStrategy $strategy;
    
    public function __construct(PaymentStrategy $strategy) {
        $this->strategy = $strategy;
    }
    
    public function executePayment(float $amount): bool {
        return $this->strategy->pay($amount);
    }
}

Observer для системы уведомлений

interface Observer {
    public function update(string $event, $data): void;
}

class NotificationService implements Observer {
    public function update(string $event, $data): void {
        if ($event === 'order_created') {
            $this->sendEmail($data['user_email'], 'Ваш заказ создан');
        }
    }
    
    private function sendEmail(string $email, string $message): void {
        // Отправка email
    }
}

class OrderManager {
    private array $observers = [];
    
    public function attach(Observer $observer): void {
        $this->observers[] = $observer;
    }
    
    public function createOrder(array $orderData): void {
        // Создание заказа
        foreach ($this->observers as $observer) {
            $observer->update('order_created', $orderData);
        }
    }
}

Decorator для добавления функциональности логирования

interface DataSource {
    public function getData(): string;
}

class DatabaseSource implements DataSource {
    public function getData(): string {
        return "Данные из базы";
    }
}

class LoggingDecorator implements DataSource {
    private DataSource $source;
    
    public function __construct(DataSource $source) {
        $this->source = $source;
    }
    
    public function getData(): string {
        $data = $this->source->getData();
        $this->log("Получены данные: " . substr($data, 0, 20));
        return $data;
    }
    
    private function log(string $message): void {
        // Запись в лог
    }
}

Выводы из практического опыта

  1. Паттерны решают типичные проблемы — они не являются "серебряной пулей", но предоставляют проверенные решения для часто встречающихся задач.

  2. Важен баланс — чрезмерное использование паттернов приводит к переусложнению, особенно в небольших проектах.

  3. В PHP особенно полезны:

    • Singleton для ресурсоёмких объектов (подключения к БД, кэширование)
    • Factory для гибкого создания объектов
    • Strategy для алгоритмов оплаты, доставки, скидок
    • Observer для событийных систем
    • Decorator для middleware в HTTP-обработчиках
  4. Современные фреймворки (Laravel, Symfony) активно используют паттерны в своей архитектуре, что подтверждает их актуальность даже спустя 30 лет после публикации.

Паттерны GoF остаются актуальными, потому что они решают фундаментальные проблемы проектирования ПО, не зависящие от конкретного языка или технологического стека. Их понимание позволяет создавать более гибкий, поддерживаемый и масштабируемый код.