2015-01-16 24 views
6

Ho avuto una domanda riguardante il "Builder Pattern" coperto da "Effective Java". Abbiamo bisogno di un metodo .build() per implementare correttamente il pattern? Per esempio, diciamo che abbiamo la seguente classe:Abbiamo bisogno di un metodo .build() nel Pattern Builder?

public class CoffeeDrink { 

    private int numEspressoShots; 
    private short milkType; 
    private boolean withWhip; 

    private CoffeeDrink() { 
    } 

    public static CoffeeDrink buildNewDrink() { 
     return new CoffeeDrink(); 
    } 

    public CoffeeDrink withEspresso(int n) { 
     this.numEspressoShots = n; 
     return this; 
    } 

    public CoffeeDrink withMilkType(shot t) { 
     this.milkType = t; 
     return this; 
    } 

    public CoffeeDrink withWhip() { 
     this.withWhip = true; 
     return this; 
    } 
} 

E allora come lo usiamo:

CoffeeDrink c = CoffeeDrink.buildNewDrink() 
         .withEspresso(2) 
         .withMilkType(2) 
         .withWhip(); 

Sarebbe questo essere ancora valida se non ho una statica interna Builder classe? Immagino che uno dei vantaggi sia che si tratti di creare un nuovo oggetto CoffeeDrink finché non viene chiamato il metodo .build(), ma sto ancora creando un oggetto Builder. Sto solo cercando alcuni chiarimenti.

+1

Il builder viene vantaggiosamente utilizzata con le classi immutabili. Con loro, il Builder è una classe "helper" mutabile che aiuta nella costruzione definitiva del prodotto finale che è quindi immutabile. Il tuo esempio è semplicemente un semplice POJO e condivide gli svantaggi di JavaBeans (modificabile, può essere visualizzato in uno stato incompleto o incoerente, ecc.). – scottb

risposta

14

No, questo non è il modello di Builder. È Java valido e verrà compilato ed eseguito. Ma il tuo metodo buildNewDrink(), che si chiami build() o buildNewDrink() o altro, è solo un semplice metodo di fabbrica che crea un CoffeeDrink. Questi altri metodi sono come metodi di setter che si ripetono.

La classe di build nidificata static è necessaria. Mentre si tiene fuori la creazione dell'istanza di classe, può eseguire la logica di convalida per garantire che non venga creato un oggetto non valido. Non sono sicuro che ci sia uno stato non valido a CoffeeDrink come tu hai, ma se lo facesse, con il tuo codice, sarebbe possibile creare uno CoffeeDrink e averlo in uno stato non valido dopo che è stato creato, ma prima sono stati chiamati altri metodi. Il modello Builder elimina questa possibilità convalidando i dati prima di creare l'istanza. Elimina anche la necessità di esplosione del costruttore, dove sono necessari molti costruttori con tutte le possibili combinazioni di parametri, per coprire tutti i possibili casi.

+0

Sono d'accordo con le vostre osservazioni. Questi metodi sembrano essere setter regolari con * concatenamento *. Solo un piccolo dettaglio, ma potrebbe mancare un * "non" * nella risposta, poiché in * "è possibile eseguire la logica di convalida per garantire che un oggetto non valido sia ** non ** creato" *. – afsantos

+0

@afsantos Grazie; corretto. – rgettman

+0

Grazie per i chiarimenti. Quindi dovrei convalidare tutti i parametri nella funzione builder della classe Builder, prima di restituire l'istanza di CoffeeDrink? – victormejia

1

In base al riferimento GoF, non è richiesto build(). Il riferimento originale non utilizza il concatenamento e il passaggio getResult() alla fine del metodo Director.construct(). La classe Director si occupa dell'incapsulamento del processo di compilazione, quindi i Client s non devono preoccuparsi se stanno costruendo le cose correttamente. È responsabilità dello Director.

Ecco il diagramma di sequenza dal riferimento GoF on Builder:

GoF Builder Sequence Diagram

Problemi correlati