Esiste una limitazione quando si utilizza il Pattern Builder di Bloch con campi obbligatori?

4

Sfondo

Ho una classe TextDrawable che disegna il testo sopra una forma. Esistono numerose proprietà che possono essere impostate durante la creazione di un oggetto TextDrawable .

Proprietà obbligatorie:

  • testo
  • Forma

Proprietà opzionali:

  • Colore
  • Larghezza
  • Altezza
  • Carattere
  • Border
  • ...
  • ... ecc.

La classe avrà costruttori che assomigliano a:

public TextDrawable(String text, Shape shape) {
}

public TextDrawable(String text, Shape shape, int color) {
}

public TextDrawable(String text, Shape shape, int color, int width, int height) {
}

// and so on..

Modello generatore :

Ho deciso di utilizzare Builder Pattern per rendere più conveniente la creazione di oggetti TextDrawable . Ho seguito il design come spiegato in Java efficace e in questa risposta altamente pubblicizzata . Ho trovato la classe builder che verrà utilizzata come segue:

TextDrawable drawable = new TextDrawable.Builder("AK", Shape.RECT)
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD)
        .build();

Possibile problema :

Sembra che ci sia un problema con questo design. Poiché i campi "obbligatori" vengono passati in constructor del builder, il builder non può essere riutilizzato.

Che cosa succede se volevo creare un altro TextDrawable della stessa altezza, larghezza, carattere ecc. ma con% diverso% di% e% di% di co_de. Dovrò creare un altro oggetto costruttore e ripetere lo stesso codice come sopra.

TextDrawable oct = new TextDrawable.Builder("OCT", Shape.RECT)
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD)
        .build();

TextDrawable nov = new TextDrawable.Builder("NOV", Shape.OVAL)
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD)
        .build();

Metodo proposto :

Cosa succede se sposto text dal costruttore del builder al metodo build come segue:

TextDrawable drawable = new TextDrawable.Builder()
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD)
        .build("AK", Shape.RECT);

In questo modo è più flessibile in quanto posso creare un'istanza del builder e riutilizzarla per creare più oggetti. (Evita anche di ripetere lo stesso codice ogni volta che creo un nuovo oggetto.) Il nuovo utilizzo sarà simile a:

TextDrawable.Builder builder = new TextDrawable.Builder()
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD);

TextDrawable oct = builder.build("OCT", Shape.RECT);
TextDrawable nov = builder.build("NOV", Shape.OVAL);

Impedisce il codice boilerplate. Permette anche al metodo di costruzione di adattarsi all'idioma fluente come segue:

TextDrawable oct = builder.buildRect("OCT");
TextDrawable nov = builder.buildOval("NOV");

Domande :

  1. Il problema identificato sopra è valido o mi manca la comprensione del color ? Non dovremmo riutilizzare mandatory parameters oggetti per creare istanze multiple?

  2. La modifica proposta al ben noto builder pattern è valida? Ci sono degli svantaggi nello spostare i "campi obbligatori" nel metodo builder ?

  3. Se ci sono alcuni possibili inconvenienti, qual è il modo migliore per ottenere ciò che voglio? Dovrei usare un oggetto builder pattern o qualcosa che incapsula il build() per ottenere quello che voglio?

posta Amulya Khare 15.10.2014 - 16:27
fonte

1 risposta

2

1. Is the problem identified above valid or do I lack understanding of the builder pattern? Should we not reuse builder objects to created multiple instances?

Può essere, a seconda della situazione. Qui hai identificato che hai campi obbligatori univoci, quindi impostarli come parametri per il tuo metodo di build ti consente di riutilizzare lo stesso builder preconfigurato più e più volte, il che è utile.

2. Is the proposed modification to the well known builder pattern valid? Are there any disadvantages of moving the "mandatory fields" into the build() method?

Per quanto riguarda i vantaggi o gli svantaggi, penso che l'altra opzione che non hai considerato qui sia quella di consentire che i campi richiesti siano impostati allo stesso modo degli altri campi. Prendi ad esempio il seguente codice:

TextDrawable.Builder builder = new TextDrawable.Builder("OCT", Shape.RECT)
        .width(10)
        .height(10)
        .useFont(Typeface.DEFAULT_BOLD);

// Make the rectangle
TextDrawable oct = builder.build();

// Build the new shape
TextDrawable oct = builder.name("NOV").shape(Shape.OVAL).build();

Ovviamente questo è molto simile a quello che avevi, e entrambi gli approcci sono ugualmente validi. Dipende davvero da quanto vuoi configurare e quanto sai cambierà sempre. Se creerai una serie di rettangoli della stessa dimensione, ma modificando solo il nome, questa soluzione ti consente di rimuovere il parametro della forma.

3. If there are some possible drawbacks, what is a better way of achieving what I want? Should I be using a director object or something that encapsulates the builder to achieve what I want?

Un direttore ti consentirebbe di impostare più facilmente i costruttori predefiniti. Potresti avere un regista per creare cerchi della stessa dimensione o un regista che accetta solo una lunghezza e crea solo quadrati. Il suo compito è quello di ridurre ulteriormente il boilerplate, ma lo fa con una maggiore complessità di classe dell'applicazione complessiva. Farei davvero questa opzione solo se ne hai assolutamente bisogno, e segui la soluzione per riutilizzare i builder laddove possibile.

    
risposta data 15.10.2014 - 17:09
fonte

Leggi altre domande sui tag