Nel 2007, ho letto un articolo su Joshua Blochs sul "builder pattern" e su come poteva essere modificato per migliorare l'uso eccessivo di costruttori e setter, specialmente quando un oggetto ha un gran numero di proprietà, molte delle quali sono opzionali. Un breve riassunto di questo modello di design è articolato qui .
Mi è piaciuta l'idea e da allora la sto usando. Il problema con esso, mentre è molto pulito e piacevole da usare dal punto di vista del cliente, implementarlo può essere un dolore per il culo! Ci sono così tanti posti diversi nell'oggetto in cui una singola proprietà è di riferimento, e quindi la creazione dell'oggetto, e l'aggiunta di una nuova proprietà richiede molto tempo.
Quindi ... ho avuto un'idea. In primo luogo, un oggetto di esempio nello stile di Joshua Bloch:
Stile Josh Bloch:
public class OptionsJoshBlochStyle {
private final String option1;
private final int option2;
// ...other options here <<<<
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private String option1;
private int option2;
// other options here <<<<<
public Builder option1(String option1) {
this.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.option2 = option2;
return this;
}
public OptionsJoshBlochStyle build() {
return new OptionsJoshBlochStyle(this);
}
}
private OptionsJoshBlochStyle(Builder builder) {
this.option1 = builder.option1;
this.option2 = builder.option2;
// other options here <<<<<<
}
public static void main(String[] args) {
OptionsJoshBlochStyle optionsVariation1 = new OptionsJoshBlochStyle.Builder().option1("firefox").option2(1).build();
OptionsJoshBlochStyle optionsVariation2 = new OptionsJoshBlochStyle.Builder().option1("chrome").option2(2).build();
}
}
Ora la mia versione "migliorata":
public class Options {
// note that these are not final
private String option1;
private int option2;
// ...other options here
public String getOption1() {
return option1;
}
public int getOption2() {
return option2;
}
public static class Builder {
private final Options options = new Options();
public Builder option1(String option1) {
this.options.option1 = option1;
return this;
}
public Builder option2(int option2) {
this.options.option2 = option2;
return this;
}
public Options build() {
return options;
}
}
private Options() {
}
public static void main(String[] args) {
Options optionsVariation1 = new Options.Builder().option1("firefox").option2(1).build();
Options optionsVariation2 = new Options.Builder().option1("chrome").option2(2).build();
}
}
Come puoi vedere nella mia "versione migliorata", ci sono 2 posti in meno in cui dobbiamo aggiungere del codice su qualsiasi proprietà di aggiunta (o opzioni, in questo caso)! L'unico aspetto negativo che riesco a vedere è che le variabili di istanza della classe esterna non possono essere definitive. Ma la classe è ancora immutabile senza questo.
C'è davvero qualche svantaggio in questo miglioramento della manutenibilità? Ci deve essere una ragione per cui ha ripetuto le proprietà all'interno della classe annidata che non vedo?