Какие группы паттернов проектирования существуют и как применить паттерн для улучшения архитектуры сервиса
Что проверяют
Две вещи: знаете ли вы классификацию и умеете ли применить паттерн к реальной проблеме сервиса, а не ради имени. Вторая важнее: следом почти всегда просят пример из вашего проекта и что в нём стало лучше.
Как отвечать
Группы GoF коротко, с примерами из Java и Spring:
- порождающие: Builder (
HttpRequest.newBuilder()), Factory Method, Singleton. В Spring бин по умолчанию и так синглтон в рамках контекста; - структурные: Adapter, Decorator, Facade, Proxy. Proxy вы используете каждый день:
@Transactionalи@Cacheableработают через прокси JDK или CGLIB; - поведенческие: Strategy, Observer (
ApplicationEventPublisherи@EventListener), Template Method (JdbcTemplate), Chain of Responsibility (цепочка фильтров Spring Security).
Вторую часть стройте от проблемы. Пример: сервис оплаты со switch по типу провайдера, каждый новый провайдер это правка того же метода и риск сломать старые ветки. Решение через Strategy: интерфейс PaymentProvider с методами supports(type) и pay(...), по реализации на провайдера, Spring внедряет их как List<PaymentProvider>, сервис выбирает нужную. Новый провайдер это новый класс, старый код не трогается, стратегии тестируются по отдельности.
Другие рабочие связки: Adapter вокруг клиента внешнего API, чтобы его модели не расползались по домену; Decorator для ретраев и метрик; Observer через события, чтобы письмо не отправлялось внутри транзакции заказа (@TransactionalEventListener по умолчанию срабатывает после коммита).
Рассказывайте свой случай и цифры: сколько было веток, сколько занимало добавление варианта, что стало с тестами. Если такого опыта нет, честно разберите гипотетический пример и назовите признаки, по которым поймёте, что паттерн нужен.
Где спотыкаются
Применяют паттерн без проблемы. Стратегия на два варианта, которые не меняются годами, это лишние классы.
Не знают, что вызов @Transactional-метода изнутри того же класса идёт мимо прокси, и транзакция не открывается.
Пишут в Spring-приложении ручной Singleton со статическим полем и двойной проверкой. Контейнер уже управляет жизненным циклом, а такой синглтон мешает тестам и подмене зависимостей.