Creazione del Java Builder per una classe in IntelliJ

1. Introduzione

Il modello di progettazione Builder è uno dei modelli di creazione più utilizzati. Ci aiuta a costruire oggetti complessi.

Scrivere i costruttori a mano è macchinoso e soggetto a errori. Pertanto, dovremmo utilizzare strumenti dedicati per generarli automaticamente quando possibile.

In questo tutorial, esploreremo diversi modi per creare automaticamente classi builder nell'IDE di IntelliJ. Daremo uno sguardo alle funzionalità integrate che IntelliJ fornisce immediatamente, nonché ai plug-in di terze parti.

2. Configurazione iniziale

In questo articolo, utilizzeremo la versione 2019.1.3 dell'edizione IntelliJ IDEA Community, che è la versione più recente al momento della scrittura. Tuttavia, tutte le tecniche presentate negli esempi dovrebbero funzionare bene anche con qualsiasi altra versione di IDEA.

Cominciamo con la definizione della classe Book per la quale genereremo un builder:

public class Book { private String title; private Author author; private LocalDate publishDate; private int pageCount; // standard constructor(s), getters and setters }

3. Utilizzo della funzionalità incorporata di IntelliJ

Per generare un builder per la classe Book utilizzando gli strumenti incorporati di IntelliJ, abbiamo bisogno di un costruttore appropriato.

Creiamone uno:

public Book(String title, Author author, LocalDate publishDate, int pageCount) { this.title = title; this.author = author; this.publishDate = publishDate; this.pageCount = pageCount; }

Ora siamo pronti per creare un builder. Quindi, posizioniamo il cursore sul costruttore creato e apriamo il popup Refactor This premendo Ctrl + Alt + Shift + T (su PC) e selezionate Sostituisci costruttore con refactoring del costruttore :

Possiamo ulteriormente modificare alcune delle opzioni per la classe builder, come il suo nome e il pacchetto di destinazione:

Di conseguenza, abbiamo generato la classe BookBuilder :

public class BookBuilder { private String title; private Author author; private LocalDate publishDate; private int pageCount; public BookBuilder setTitle(String title) { this.title = title; return this; } public BookBuilder setAuthor(Author author) { this.author = author; return this; } public BookBuilder setPublishDate(LocalDate publishDate) { this.publishDate = publishDate; return this; } public BookBuilder setPageCount(int pageCount) { this.pageCount = pageCount; return this; } public Book createBook() { return new Book(title, author, publishDate, pageCount); } }

3.1. Prefisso dei setter personalizzati

È pratica comune utilizzare un prefisso with per i metodi setter nelle classi builder.

Per cambiare il prefisso predefinito, dobbiamo scegliere l' icona Rinomina prefisso setter nell'angolo in alto a destra della finestra delle opzioni :

3.2. Costruttore interno statico

Alcuni di noi potrebbero preferire implementare i builder come classi interne statiche come descritto da Joshua Bloch in Effective Java .

In tal caso, è necessario eseguire alcuni passaggi aggiuntivi per ottenere ciò utilizzando la funzione Sostituisci costruttore con Builder di IntelliJ .

Prima di tutto, dobbiamo creare manualmente una classe interna vuota e rendere privato il costruttore:

public class Book { private String title; private Author author; private LocalDate publishDate; private int pageCount; public static class Builder { } private Book(String title, Author author, LocalDate publishDate, int pageCount) { this.title = title; this.author = author; this.publishDate = publishDate; this.pageCount = pageCount; } // standard getters and setters }

Inoltre, dobbiamo scegliere Usa esistente nella finestra delle opzioni e puntare alla nostra classe appena creata:

4. Utilizzo del plugin InnerBuilder

Vediamo ora come possiamo generare un builder per la classe Book usando il plugin InnerBuilder.

Una volta installato il plugin, possiamo aprire il pop-up Genera premendo Alt + Ins (su PC) e scegliendo l' opzione Builder… :

In alternativa, possiamo chiamare direttamente il plugin InnerBuilder premendo Alt + Maiusc + B (su PC):

Come vediamo, ci sono alcune opzioni tra cui possiamo scegliere per personalizzare il builder generato.

Vediamo il builder generato quando tutte le opzioni sono deselezionate:

public static final class Builder { private String title; private Author author; private LocalDate publishDate; private int pageCount; public Builder() { } public Builder title(String val) { title = val; return this; } public Builder author(Author val) { author = val; return this; } public Builder publishDate(LocalDate val) { publishDate = val; return this; } public Builder pageCount(int val) { pageCount = val; return this; } public Book build() { return new Book(this); } }

Il plugin InnerBuilder implementa i builder come classi interne statiche per impostazione predefinita.

5. Utilizzando Builder Generator Plugin

Infine, vediamo come funziona Builder Generator.

Allo stesso modo, come per InnerBuilder, possiamo premere Alt + Ins (su PC) e scegliere l' opzione Builder o utilizzare la scorciatoia Alt + Maiusc + B.

Come possiamo vedere, abbiamo tre opzioni tra cui scegliere per personalizzare il BookBuilder :

Lasciamo tutte le opzioni deselezionate e vediamo la classe del generatore generata:

public final class BookBuilder { private String title; private Author author; private LocalDate publishDate; private int pageCount; private BookBuilder() { } public static BookBuilder aBook() { return new BookBuilder(); } public BookBuilder withTitle(String title) { this.title = title; return this; } public BookBuilder withAuthor(Author author) { this.author = author; return this; } public BookBuilder withPublishDate(LocalDate publishDate) { this.publishDate = publishDate; return this; } public BookBuilder withPageCount(int pageCount) { this.pageCount = pageCount; return this; } public Book build() { Book book = new Book(); book.setTitle(title); book.setAuthor(author); book.setPublishDate(publishDate); book.setPageCount(pageCount); return book; } }

La prima opzione che il plugin Builder Generator fornisce per personalizzare la classe builder creata - Inner builder - è piuttosto autoesplicativa.

Altri due, tuttavia, sono più interessanti e li esploreremo nelle sezioni seguenti.

5.1. Opzione del metodo "but"

Se scegliamo questa opzione, il plugin aggiungerà un metodo but () alla classe BookBuilder :

public BookBuilder but() { return aBook().withTitle(title).withAuthor(author) .withPublishDate(publishDate).withPageCount(pageCount); }

Now, let's imagine we want to create three books with the same author and the same number of pages but with different titles and publish dates. We may create a base builder with common properties already set and then use the but() method to create new BookBuilders (and Books later on) out of it.

Let's take a look at an example:

BookBuilder commonBuilder = BookBuilder.aBook().withAuthor(johnDoe).withPageCount(123); Book my_first_book = commonBuilder.but() .withPublishDate(LocalDate.of(2017, 12, 1)) .withTitle("My First Book").build(); Book my_second_book = commonBuilder.but() .withPublishDate(LocalDate.of(2018, 12, 1)) .withTitle("My Second Book").build(); Book my_last_book = commonBuilder.but() .withPublishDate(LocalDate.of(2019, 12, 1)) .withTitle("My Last Book").build();

5.2. Use a Single Field Option

If we choose this option, the generated builder will hold a reference to the created Book object instead of all the book's properties:

public final class BookBuilder { private Book book; private BookBuilder() { book = new Book(); } public static BookBuilder aBook() { return new BookBuilder(); } public BookBuilder withTitle(String title) { book.setTitle(title); return this; } public BookBuilder withAuthor(Author author) { book.setAuthor(author); return this; } public BookBuilder withPublishDate(LocalDate publishDate) { book.setPublishDate(publishDate); return this; } public BookBuilder withPageCount(int pageCount) { book.setPageCount(pageCount); return this; } public Book build() { return book; } }

This is a bit different approach to create a builder class that might come in handy in certain situations.

6. Conclusion

In this tutorial, we've explored different ways to generate builder classes in IntelliJ.

Di solito è meglio usare questo tipo di strumenti per generare automaticamente i nostri builder . Ciascuna delle opzioni che abbiamo presentato ha i suoi pro e contro. L'approccio che scegliamo effettivamente è piuttosto una questione di gusti e preferenze individuali.