Ломбок @Builder по методу

Я хочу использовать свободный API, чтобы уменьшить список параметров метода. Я не хочу создавать для этого конструктор, поэтому аннотирую метод Lombok-@Builder:

@Builder
public static void test(User user, Item item, int age, Map<String, Test> tests, LocalDateTime time, String desc){
        ..method related things..
}

Теперь я рассчитываю вызвать этот метод с помощью Fluent-Api @Builder:

test.withUser(u).withItem(i)...build();

Однако, поскольку у меня нет геттеров и сеттеров для этого метода, для этого метода не существует свободного API. Это правильное использование @Builder в методе?


person nimo23    schedule 06.09.2017    source источник
comment
Честно говоря, я когда-либо использовал Builder только на уроках. Я даже не знал, что ты можешь поставить это на метод. Я бы полностью реорганизовал кучу таких параметров в один класс с помощью Builder. В Java нет ничего менее читаемого, чем метод с кучей параметров.   -  person Novaterata    schedule 07.09.2017


Ответы (1)


Вот как вы используете синтаксис Builder по умолчанию.

@Builder
public static void test(User user, Item item){
    // ...
}

public void buildTestExample(){
    builder()
            .user(new User())
            .item(new Item())
            .build();
}

Однако вы можете указать имя метода следующим образом:

@Builder(builderMethodName = "buildTest")
public static void test(User bar, Item item){
    // ...
}

public void buildTestExample(){
    buildTest()
            .user(new User())
            .item(new Item())
            .build();
}

См. https://projectlombok.org/features/Builder.

Метод, аннотированный @Builder (отныне называемый target), вызывает создание следующих 7 вещей:

  • Внутренний статический класс с именем FooBuilder с аргументами того же типа, что и статический метод (называемый построителем).
  • В билдере: Одно приватное нестатическое нефинальное поле для каждого параметра таргета.
  • В построителе: пустой конструктор пакета без аргументов.
  • В построителе: метод, подобный «сеттеру», для каждого параметра цели: он имеет тот же тип, что и этот параметр, и то же имя. Он возвращает сам построитель, так что вызовы сеттера могут быть связаны, как в приведенном выше примере.
  • В построителе: метод build(), который вызывает метод, передавая каждое поле. Он возвращает тот же тип, что и цель.
  • В построителе: разумная реализация toString().
  • В классе, содержащем цель: метод builder(), который создает новый экземпляр построителя.

Вот произвольный пример, показывающий, что у вас может быть 2 Builder для 2 методов, и он отлично работает.

@Builder(builderMethodName = "buildFoo")
public static String foo(String param1, String param2){
    return "foo" + param1 + param2;
}

@Builder(builderMethodName = "buildBar")
public static String bar(String param1, String param2){
    return "bar" + param1 + param2;
}

@Test
public void test(){

   assertThat(buildFoo().param1("h").param2("w").build()).isEqualTo("foohw");

   assertThat(buildBar().param1("h").param2("w").build()).isEqualTo("foohw");
}
person Novaterata    schedule 06.09.2017
comment
Использование типа возвращаемого значения без void, такого как @Builder(builderMethodName = buildTest) public static Output test(User bar, Item item){ // ... } не работает. Отладчик говорит: Тип возвращаемого значения для метода отсутствует - person nimo23; 06.09.2017
comment
имея два метода с аннотацией @Builder, только первый метод с аннотацией @Builder перезаписывает toString. Но почему я вынужден перезаписывать toString только для того, чтобы использовать fluent-Api для метода? - person nimo23; 06.09.2017
comment
Возможно, лучшим способом было бы иметь новую аннотацию в ломбоке, например @Fluent, которая может быть аннотирована только для метода и позволяет свободно вызывать метод со всеми его свойствами. Например, method().addPropX().addPropY().invoke(); - person nimo23; 06.09.2017
comment
@ nimo23 Это был ответ на твой вопрос, ты двигаешь стойку ворот, но я постараюсь решить твою проблему. Синтаксис builder().paramName("foo).build(). Вы можете изменить builder() и build(), но я не думаю, что вы можете изменить .paramName("foo") на .addParamName("foo") или что-то еще. - person Novaterata; 07.09.2017
comment
Я не могу отлаживать остальную часть вашего кода без вашего предоставления, но это должно полностью ответить на ваш вопрос. - person Novaterata; 07.09.2017
comment
Спасибо за это. Думаю, я буду использовать объект и передавать объект вместо длинного списка параметров. Кстати, я создал задачу github.com/rzwitserloot/lombok/issues/1464. Может быть, ломбок может улучшить беглый API, особенно для вызовов методов. - person nimo23; 07.09.2017
comment
@ nimo23 Я не понимаю, это именно то, что вы сказали, что хотели сделать. - person Novaterata; 07.09.2017
comment
Да, ты прав. Это решило проблему, но существуют ограничения с аннотацией @Builder, такие как обязательные параметры. И вызовы методов... когда String возвращается для двух методов, тогда ломбок создает StringBuilder, который имеет все параметры двух методов... так что это не разделено. - person nimo23; 07.09.2017
comment
Я просто не вижу поведения, при котором параметры объединяются для двух методов, если builderMethodName отличается. - person Novaterata; 07.09.2017
comment
Вы можете использовать builderClassName = "Builder1", чтобы изменить имя класса строителя из StringBuilder или что-то еще - person Novaterata; 07.09.2017