> С какими паттернами проектирования ты работал (PHP)
Уровень: senior · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: vanta
Стек: PHP
> Пример ответа
Короткий ответ
В основном работал с порождающими, структурными и поведенческими паттернами из GoF: Factory, Abstract Factory, Builder, Singleton, Adapter, Facade, Decorator, Proxy, Observer, Strategy, Template Method, Repository, Service Locator, Dependency Injection. В PHP-проектах чаще всего применял Repository, Factory, Strategy, Observer и DI-контейнеры. Также использовал паттерны уровня архитектуры: MVC, Middleware, Event-Driven, CQRS (частично), Unit of Work через ORM.
Подробное объяснение
Паттерны проектирования - это переиспользуемые решения типовых задач. В PHP, особенно в legacy-коде и современных фреймворках (Symfony, Laravel), они проявляются по-разному.
Порождающие паттерны - управление созданием объектов:
- Factory Method - создание объекта через метод вместо
newнапрямую. Используется в Doctrine, когда сущности создаются черезEntityManager. - Abstract Factory - семейство связанных объектов. Например, фабрика для разных типов платежных провайдеров.
- Builder - пошаговое создание сложного объекта. Применяется для конфигураций, запросов к БД (QueryBuilder в Doctrine).
- Singleton - гарантирует один экземпляр класса. В PHP часто критикуется, но используется для логгеров, кэш-сервисов.
Структурные паттерны - композиция классов:
- Adapter - преобразует интерфейс одного класса к другому. Классика: обертки над сторонними API.
- Decorator - добавляет поведение объекту без изменения его кода. В PHP часто используется для middleware-цепочки, для кэширования репозиториев.
- Facade - упрощенный интерфейс к сложной подсистеме. Например, сервис-фасад для работы с несколькими репозиториями.
- Proxy - ленивая загрузка, контроль доступа. Doctrine Proxy для lazy loading сущностей.
Поведенческие паттерны - взаимодействие между объектами:
- Observer - событийная модель. В Symfony - EventDispatcher, в Laravel - Events.
- Strategy - выбор алгоритма в рантайме. Например, разные стратегии валидации, скидок, экспорта.
- Template Method - скелет алгоритма, переопределяемый в подклассах. Часто используется в абстрактных сервисах.
- Repository - абстракция над хранилищем данных. Стандарт в Doctrine, Eloquent.
- Dependency Injection - внедрение зависимостей через конструктор или сеттеры. Основа Symfony DI-контейнера.
Также на практике встречаются:
- Middleware (PSR-15) - цепочка обработки запроса.
- Service Locator - антипаттерн, но встречается в старых кодовых базах.
- Unit of Work - реализован в Doctrine, отслеживает изменения сущностей.
- Null Object - заглушка вместо null-проверок.
На практике
В реальных PHP-проектах паттерны редко применяются изолированно. Обычно они комбинируются:
- Repository + Factory + DI - типичная связка для работы с БД.
- Strategy + Factory - выбор алгоритма на основе конфигурации.
- Observer + Event-Driven - для асинхронных уведомлений, аудита, логирования.
- Decorator + Middleware - для обработки HTTP-запросов.
Важно понимать trade-off: паттерн добавляет абстракцию и сложность. В простых CRUD-проектах Repository и Factory избыточны. Я применяю паттерны осознанно, когда есть реальная потребность в расширяемости, тестируемости или переиспользовании.
Также стоит упомянуть, что в PHP-фреймворках многие паттерны уже встроены: DI-контейнер, EventDispatcher, Middleware, Repository (через ORM). Поэтому часто достаточно правильно использовать фреймворк, а не писать паттерны вручную.
Пример кода
PHP// Пример комбинации Factory + Strategy + Repositoryinterface PaymentGateway{public function charge(float $amount): bool;}class StripeGateway implements PaymentGateway{public function charge(float $amount): bool{// логика Stripereturn true;}}class PayPalGateway implements PaymentGateway{public function charge(float $amount): bool{// логика PayPalreturn true;}}class PaymentGatewayFactory{public function create(string $type): PaymentGateway{return match ($type) {'stripe' => new StripeGateway(),'paypal' => new PayPalGateway(),default => throw new \InvalidArgumentException("Unknown gateway: $type"),};}}class OrderRepository{public function find(int $id): Order{// Doctrine или PDO}}class PaymentService{public function __construct(private PaymentGatewayFactory $factory,private OrderRepository $repository,) {}public function pay(int $orderId, string $gatewayType): bool{$order = $this->repository->find($orderId);$gateway = $this->factory->create($gatewayType);return $gateway->charge($order->total);}}
Как отвечать на собеседовании
Начни с перечисления основных групп паттернов, затем приведи 2-3 конкретных примера из своего опыта. Обязательно объясни, почему выбрал именно этот паттерн, а не другой. Покажи понимание trade-off: когда паттерн полезен, а когда избыточен. Если просят пример кода - пиши короткий, но рабочий фрагмент, комментируя ключевые решения. Не перечисляй все паттерны подряд без контекста - это выглядит как заучивание. Лучше глубоко разобрать 3-4 паттерна, чем поверхностно упомянуть 15. Также упомяни, как паттерны реализованы во фреймворках, которыми пользуешься.
Что проверяет интервьюер
Интервьюер оценивает:
- понимание назначения паттернов, а не только названия;
- способность применить паттерн к реальной задаче;
- осознание альтернатив и trade-off;
- знание, как паттерны встроены в PHP-фреймворки;
- умение объяснить код и обосновать выбор.
На senior-уровне важно показать, что ты не используешь паттерны ради паттернов, а решаешь конкретные проблемы: тестируемость, расширяемость, снижение связанности. Также ценится умение критиковать паттерны: например, Singleton - антипаттерн в большинстве случаев, Service Locator - скрытая зависимость.
Типичные ошибки
- Перечисление всех паттернов без примеров - звучит как шпаргалка.
- Применение паттернов там, где они не нужны - оверинжиниринг.
- Путаница между похожими паттернами: Factory vs Abstract Factory, Strategy vs Template Method, Decorator vs Proxy.
- Непонимание, как паттерн реализован в конкретном фреймворке.
- Игнорирование альтернатив: например, вместо Observer можно использовать простой callback или шину событий.
- Утверждение, что Singleton - хороший паттерн, без оговорок о его проблемах с тестированием и состоянием.
> Похожие задачи по PHP
Как оптимизировать алгоритм поиска уникального элемента без дополнительной памяти
Какие принципы проектирования кроме SOLID существуют
Как изменить взаимодействие между сервисами, чтобы избежать дублирования заказов при ретраях
Как изменить взаимодействие с внешним сервисом, чтобы избежать увеличения нагрузки из-за ретраев
> Похожие задачи по backend
Как оптимизировать алгоритм поиска уникального элемента без дополнительной памяти
Какие принципы проектирования кроме SOLID существуют
Как изменить взаимодействие между сервисами, чтобы избежать дублирования заказов при ретраях
Как изменить взаимодействие с внешним сервисом, чтобы избежать увеличения нагрузки из-за ретраев
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью