Какие паттерны проектирования ты знаешь и применял?

«Какие паттерны проектирования ты знаешь и применял?» — вопрос из категории Паттерны, который задают на 49% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В своей практике я чаще всего применяю следующие паттерны, разделяя их по целям:

Порождающие (Creational):

  • Фабричный метод (Factory Method) / Абстрактная фабрика (Abstract Factory): Использовал для создания семейств связанных объектов, например, различных провайдеров аутентификации (OAuth, JWT, LDAP) или парсеров разных форматов логов (JSON, XML, CSV). Это позволяет изолировать логику создания.
  • Строитель (Builder): Применял для пошагового конструирования сложных объектов конфигурации или DTO с множеством необязательных полей, что делает код чище, чем вызов конструктора с десятком параметров.
  • Внедрение зависимостей (Dependency Injection): Основа большинства современных фреймворков. Активно использую для повышения тестируемости и уменьшения связности компонентов.

Структурные (Structural):

  • Адаптер (Adapter): Интегрировал сторонние библиотеки или legacy-код, создавая класс-обертку с нужным интерфейсом.
  • Декоратор (Decorator): Использовал для динамического добавления функциональности, например, добавления логирования, кэширования или проверки прав доступа к основному сервису без изменения его кода.
  • Фасад (Facade): Создавал упрощенные интерфейсы для работы со сложными подсистемами (например, модулем отчетности или интеграцией с внешним API).

Поведенческие (Behavioral):

  • Стратегия (Strategy): Применял для инкапсуляции алгоритмов, которые могут меняться (например, алгоритмы сортировки, стратегии расчета скидок или способы отправки уведомлений — email, SMS, push). Это позволяет легко подменять их в runtime.
  • Наблюдатель (Observer): Реализовывал для построения систем событий (event-driven). Например, при изменении статуса заказа автоматически запускались обработчики для отправки уведомления клиенту, обновления склада и логирования.
  • Команда (Command): Использовал для инкапсуляции запросов как объектов, что полезно для реализации очереди задач, отмены операций (undo/redo) или отложенного выполнения.

Пример Стратегии на Java для валидации:

// Интерфейс стратегии
interface ValidationStrategy {
    boolean execute(String data);
}

// Конкретные стратегии
class EmailValidation implements ValidationStrategy {
    public boolean execute(String data) {
        return data.matches("^[^@]+@[^@]+\.[^@]+$");
    }
}
class PhoneValidation implements ValidationStrategy {
    public boolean execute(String data) {
        return data.matches("^\+?[0-9]{10,}$");
    }
}

// Контекст, использующий стратегию
class Validator {
    private ValidationStrategy strategy;
    public Validator(ValidationStrategy strategy) {
        this.strategy = strategy;
    }
    public boolean validate(String input) {
        return strategy.execute(input);
    }
}

// Использование
Validator emailValidator = new Validator(new EmailValidation());
boolean isValid = emailValidator.validate("test@example.com");

Ключевой принцип — не использовать паттерны ради самих паттернов, а применять их для решения конкретных проблем проектирования, таких как снижение связанности, повышение гибкости или улучшение тестируемости кода.

Видео-ответы