Обновить

Комментарии 5

Джошуа Блох советует в данном случае со switch использовать внутренний класс-стратегию внутри вашего enum, чтобы избавиться от switch.
Не спорю, данный вариант тоже подходит, но суть архитектуры в том, что она завязана на дженериках и трансферах, а в случае, который советует Блох получается сильная привязка к enum — у, чего мне совсем не хотелось, т к данное поле изначально не являлось обязательным для бизнес логики.

Проблема также решается без Spring с помощью Java Service Providers.
https://docs.oracle.com/javase/tutorial/ext/basics/spi.html
Можно динамически подгружать реализации некоторого интерфейса и его билдера и выбирать их по какой-нибудь метаинформации без switch (итерируя доступные в рантайме и выбирая нужную).

Посмею сделать небольшое замечание, по поводу автовайринга ApplicationContext-а в фабрику. Это, как заверяют евангелисты, признак плохого тона. Не должен отдельный компонент знать про весь контекст. Думаю фабрику можно переписать иначе:

    @SuppressWarnings("unchecked")
    @Component
    public class RequestBuildersFactoryImpl implements RequestBuildersFactory {
    
        @Setter(onMethod = @__(@Autowired))
        private List<RequestBuilder> builders;
    
        public <T extends Transfer> BaseRequest<T> transferToRequest(T transfer) {
    
            ResolvableType type = ResolvableType.forClassWithGenerics(RequestBuilder.class, transfer.getClass());

            RequestBuilder<T> builder = builders.stream().filter(b -> type::isInstance).findFirst().get();
    
            return builder.createRequest(transfer, stage);
        }    
    }


В части получения билдера из списка могут быть варианты, но основной посыл надеюсь понятен.
Спасибо за комментарий, давно увидел его, никак руки не доходили исправить)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации