1. Panoramica
@Builder di Project Lombok è un meccanismo utile per utilizzare il pattern Builder senza scrivere codice boilerplate. Possiamo applicare questa annotazione a una classe oa un metodo.
In questo breve tutorial, esamineremo i diversi casi d'uso di @Builder .
2. Dipendenze di Maven
Innanzitutto, dobbiamo aggiungere Project Lombok al nostro pom.xml :
org.projectlombok lombok 1.18.10
Maven Central ha l'ultima versione di Project Lombok qui.
3. Utilizzo di @Builder su una classe
Nel primo caso d'uso, stiamo semplicemente implementando una classe e vogliamo utilizzare un builder per creare istanze della nostra classe.
Il primo e unico passaggio è aggiungere l'annotazione alla dichiarazione della classe:
@Getter @Builder public class Widget { private final String name; private final int id; }
Lombok fa tutto il lavoro per noi. Ora possiamo creare un widget e testarlo:
Widget testWidget = Widget.builder() .name("foo") .id(1) .build(); assertThat(testWidget.getName()) .isEqualTo("foo"); assertThat(testWidget.getId()) .isEqualTo(1);
Se vogliamo creare copie o quasi copie di oggetti, siamo in grado di aggiungere la proprietà toBuilder = true alla @Builder annotazioni :
@Builder(toBuilder = true) public class Widget { //... }
Questo dice a Lombok di aggiungere un metodo toBuilder () alla nostra classe . Quando invochiamo il metodo toBuilder () , restituisce un builder inizializzato con le proprietà dell'istanza su cui è chiamato:
Widget testWidget = Widget.builder() .name("foo") .id(1) .build(); Widget.WidgetBuilder widgetBuilder = testWidget.toBuilder(); Widget newWidget = widgetBuilder.id(2).build(); assertThat(newWidget.getName()) .isEqualTo("foo"); assertThat(newWidget.getId()) .isEqualTo(2);
Possiamo vedere nel codice del test che la classe builder generata da Lombok è chiamata come la nostra classe, con "Builder" aggiunto ad essa - WidgetBuilder in questo caso. Possiamo quindi modificare le proprietà che desideriamo e costruire () una nuova istanza.
Se dobbiamo specificare i campi obbligatori, possiamo utilizzare la configurazione dell'annotazione per creare un generatore ausiliario:
@Builder(builderMethodName = "internalBuilder") public class RequiredFieldAnnotation { @NonNull private String name; private String description; public static RequiredFieldAnnotationBuilder builder(String name) { return internalBuilder().name(name); } }
In questo caso, nascondiamo il builder predefinito come internalBuilder e creiamo il nostro. Pertanto, quando creiamo il builder, dobbiamo fornire il parametro richiesto:
RequiredField.builder("NameField").description("Field Description").build();
Inoltre, per assicurarci che il nostro campo esista, possiamo aggiungere l' annotazione @NonNull .
4. Utilizzo di @Builder su un metodo
Supponiamo di utilizzare un oggetto che vogliamo costruire con un builder, ma non possiamo modificare il sorgente o estendere la classe .
Innanzitutto, creiamo un rapido esempio utilizzando l'annotazione @Value di Lombok:
@Value final class ImmutableClient { private int id; private String name; }
Ora abbiamo una classe finale con due membri immutabili, getter per loro e un costruttore di tutti gli argomenti.
Abbiamo spiegato come usare @Builder su una classe , ma possiamo usarlo anche sui metodi. Useremo questa capacità per aggirare l'impossibilità di modificare o estendere ImmutableClient .
Successivamente, creeremo una nuova classe con un metodo per creare ImmutableClients:
class ClientBuilder { @Builder(builderMethodName = "builder") public static ImmutableClient newClient(int id, String name) { return new ImmutableClient(id, name); } }
Questa annotazione crea un metodo denominato builder () che restituisce un Builder per la creazione di ImmutableClients .
Ora, costruiamo un ImmutableClient :
ImmutableClient testImmutableClient = ClientBuilder.builder() .name("foo") .id(1) .build(); assertThat(testImmutableClient.getName()) .isEqualTo("foo"); assertThat(testImmutableClient.getId()) .isEqualTo(1);
5. conclusione
In questo articolo, abbiamo utilizzato l' annotazione @Builder di Lombok su un metodo per creare un builder per una classe finale e abbiamo visto come rendere obbligatori alcuni campi della classe .
Esempi di codice, come sempre, possono essere trovati su GitHub.