Pattern del costruttore graduale
Sia le factory statiche che i costruttori hanno difficoltà a gestire un gran numero di parametri. Ad esempio, se una classe ha 6 campi e si desidera creare costruttori che accettano 2 parametri, 3 parametri, ecc., è possibile utilizzare il pattern del costruttore graduale, come mostrato di seguito.
Tuttavia, anche questo approccio diventa difficile da leggere quando il numero di parametri aumenta, rendendo difficile capire il significato di ogni valore e portando a possibili errori di input di parametri dello stesso tipo.
Java Beans Pattern
Il Java Beans Pattern crea un oggetto tramite un costruttore senza parametri e quindi imposta i valori desiderati per i parametri tramite i metodi setter.
Il Java Beans Pattern consente di creare istanze senza confondere i parametri, anche quando sono molti. Tuttavia, richiede diverse chiamate ai metodi setter per creare un oggetto e, fino a quando l'oggetto non è completamente definito, la coerenza non è garantita. Questo rende impossibile rendere la classe immutabile.
Pattern Builder
Il Pattern Builder combina la sicurezza del pattern del costruttore graduale con la leggibilità del Java Beans Pattern, ed è il pattern più utilizzato.
Invece di creare l'oggetto direttamente, il client chiama il costruttore con solo i parametri obbligatori per ottenere un oggetto Builder. Quindi, utilizza una serie di metodi setter, forniti dall'oggetto Builder, per impostare i parametri opzionali. Infine, chiama il metodo build(), senza parametri, per ottenere l'oggetto desiderato.
La classe Builder accetta solo i parametri obbligatori nel suo costruttore, mentre i parametri opzionali vengono impostati tramite i metodi setter. Infine, il metodo build() crea l'oggetto NutritionFactsWithBuilderPattern completo. La classe NutritionFactsWithBuilderPattern è immutabile e i metodi setter del builder restituiscono il builder stesso, consentendo una chiamata a catena. Questo approccio è chiamato Fluent API o Method Chaining.
Dal punto di vista del client, il pattern Builder rende il codice più facile da scrivere e da leggere.
Il pattern Builder si adatta bene alle classi gerarchiche
La classe Pizza.Builder è un tipo generico che utilizza la limitazione di tipo ricorsiva, e aggiunge il metodo astratto self() per consentire alle sottoclassi di supportare il chaining senza dover effettuare alcun cast. Nelle sottoclassi, questo metodo astratto deve restituire se stesso.
Vediamo ora le pizze di New York e Calzone, sottoclassi di Pizza, per comprendere la flessibilità del pattern Builder.
Il metodo build() di ogni sottoclasse Builder restituisce la sottoclasse concreta. Questa funzionalità, in cui un metodo di una sottoclasse restituisce un tipo che è un sottotipo del tipo restituito dal metodo corrispondente nella superclasse, è chiamata "covariant return typing". Grazie a questa funzionalità, il client non ha bisogno di effettuare alcun cast.
Il client può utilizzare sia gli enum di Pizza che quelli delle sottoclassi, e può completare l'oggetto tramite i metodi appropriati.
Svantaggi del pattern Builder
- È necessario creare un oggetto Builder.
- Il codice può diventare prolisso.
Riepilogo
Se un costruttore o un metodo factory statico deve gestire un gran numero di parametri, si può prendere in considerazione l'utilizzo del pattern Builder.
Fonti
- Effective Java
Commenti0