Gli argomenti con nome sostituiscono il modello di generatore?


20

Quando si utilizza un linguaggio che supporta argomenti con nome e facoltativi, il modello del builder non ha più un uso pratico?

Costruttore:

new Builder(requiredA, requiredB).setOptionalA("optional").Build();

Argomenti opzionali / nominati:

new Object(requiredA, requiredB, optionalA: "optional");

3
Come gestite 20 argomenti opzionali? Non c'è un problema che il costruttore deve risolvere fino a quando non diventa grande. Nel punto che hai descritto qui hai due costruttori (e non costruirò un costruttore per quel piccolo problema).

1
Anche con argomenti opzionali - se il costruttore ha più di 2 argomenti, preferisco usare un oggetto valore per incapsulare la configurazione. Lo stesso vale per le superfici fluide e il costruttore: qualsiasi cosa maggiore di 3 verrebbe sostituita da un oggetto valore.
Thomas Junk,

Risposte:


21

I costruttori sono molto utili quando il tuo oggetto ha bisogno di molti argomenti / dipendenze per essere utile, o se vuoi consentire molti modi diversi di costruire l'oggetto.

Dalla parte superiore della mia testa, posso immaginare che qualcuno potrebbe voler "costruire" oggetti in un gioco 3D come questo:

// Just ignore the fact that this hypothetical god class is coupled to everything ever
new ObjectBuilder(x, y, z).importBlenderMesh("./meshes/foo")
                          .syncWithOtherPlayers(serverIP)
                          .compileShaders("./shaders/foo.vert", "./shaders/foo.frag")
                          .makeDestructibleRigidBody(health, weight)
                          ...

Direi che questo esempio è più leggibile con i metodi builder che ho inventato proprio ora che con i parametri opzionali:

new Object(x, y, z, meshType: MESH.BLENDER,
                    meshPath: "./meshes/foo",
                    serverToSyncWith: serverIP,
                    vertexShader: "./shaders/foo.vert",
                    physicsType: PHYSICS_ENGINE.RIGID_DESTRUCTIBLE,
                    health: health,
                    weight: weight)
                    ...

In particolare, le informazioni implicite dai nomi dei metodi del builder devono essere sostituite da ancora più parametri, ed è molto più facile dimenticare un parametro in un gruppo di parametri strettamente correlati. In realtà, lo shader di frammenti manca, ma non lo noteresti a meno che non sapessi cercarlo.


Naturalmente, se il tuo oggetto richiede solo da uno a cinque argomenti per la costruzione, non è necessario coinvolgere il modello di builder, indipendentemente dal fatto che tu abbia o meno dei parametri nominati / opzionali.


Non compro i tuoi argomenti. Se i nomi dei metodi del builder sono così meravigliosi, puoi usarli anche per i nomi dei parametri. Se i parametri sono strettamente correlati, inseriscili in un piccolo costruttore di oggetti.
user949300

@ user949300 Penso che tu abbia perso la parte importante del punto, che è che i metodi del builder qui descrivono le relazioni tra i parametri che si perdono se hai solo un mucchio di parametri opzionali. Nell'esempio del costruttore di Ixrec, "salute" e "peso" sono chiaramente logicamente parte delle impostazioni del corpo distruttibile, ma quella relazione viene persa nella versione dell'argomento opzionale.
Jules,

1
non se uno dei parametri opzionali è (body: new DestructibleRigidBody (salute, peso), ...)
Weyland Yutani

@Jules. Quello che ha detto Weyland: crea un costruttore poco noto per peso e altezza.
user949300

8

Oltre a ciò che ha detto Ixrec, i costruttori o il metodo chiamato parametri non ti permetteranno di avere il tuo oggetto in uno stato da costruire in cui può ancora essere modificato prima di costruirlo. Questa è la bellezza del Builder, in cui puoi delegare parti della sua costruzione a diversi metodi o classi contemporaneamente:

var myThingBuilder = new ThingBuilder("table");
myThingBuilder.setAttribute(Attributes.Legs, 4);

inventoryManager.setPrices(myThingBuilder);

// inventory manager
var availableCheapestMaterial = getMaterial();
myThingBuilder.setMaterial(availableCheapestMaterial);

Fondamentalmente, sei anche in grado di gettare il tuo costruttore nel tuo sistema fino a quando non è pronto per costruire l'oggetto finale, permettendoti di ridurre la quantità di conoscenza che il tuo costruttore-consumatore deve avere.


Non capisco il tuo ultimo paragrafo. Se "getti il ​​tuo costruttore nel sistema fino a quando non è pronto", ha troppa conoscenza del sistema. Il tuo ThingBuilder conosce gli attributi, viene misteriosamente modificato da InventoryManager e conosce i materiali. Non vedere come questo sta diminuendo la conoscenza.
user949300

@ user949300 Pensa a come sarebbe senza il costruttore che viaggia attraverso il sistema. Saresti costretto ad avere una classe con un grande fattore di fan-out, ed è solo necessario per costruire la Cosa. (Naturalmente, supponendo che la tua classe non concentri tutte le conoscenze, questo è ciò che volevamo evitare in primo luogo.) Ora, se questa classe ha altre responsabilità, stai creando una classe enorme, rompendo S in SOLID . Se questa è l'unica responsabilità, ti stai trasformando in ThingBuilder.
Alpha

1

Dipende da cosa stai facendo con il costruttore.

Se si utilizza il builder solo per impostare (e variare) le proprietà degli oggetti e (differire) la creazione degli oggetti, è possibile sostituirli con parametri nominati.

Sostituendo il builder potresti avere il compromesso di leggibilità / utilizzo menzionato da @Ixrec (o potrebbe non averlo, dipende da cosa stai facendo con il builder).

Tuttavia, se il tuo costruttore non si limita a mantenere le proprietà e ogni passaggio di costruzione implica la logica, non può essere sostituito.

MockBuilder è un esempio in cui non può essere sostituito con parametri nominati. Dalla pagina:

La logica della procedura di creazione non può essere sostituita con parametri nominati


-5

Il modello del generatore è essenziale quando si lavora con oggetti immutabili. Ci sono molti vantaggi nel lavorare con oggetti immutabili, specialmente nel rendere il tuo programma più robusto eseguendolo in un ambiente concorrente (es. Thread)


3
Sì, i costruttori sono perfetti per lavorare con oggetti immutabili complessi (o anche con oggetti mutabili) prima di poterlo utilizzare, devi assicurarti che l'oggetto sia in uno stato coerente. Detto questo, new Integer(42), new BigDecimal("42.000")e new String("foobar")sono tutti i costruttori a immutabili che ... beh, un costruttore sarebbe inutilmente complessa per questi casi. Quindi un costruttore non è essenziale per lavorare con immutabile quando i costruttori possono funzionare altrettanto bene.

Sì, un costruttore può essere utilizzato con oggetti immutabili, che non viene negato. Ma la domanda originale era se il modello Builder avesse qualche utilità pratica a parte gli argomenti opzionali e la mia risposta era di chiarire questo.
codedabbler

2
La domanda originale non dice nulla sugli oggetti immutabili. Si sta chiedendo dei parametri nominati e della relazione con loro con i costruttori. La tua risposta riguarda il costruttore e la sua relazione con oggetti immutabili. Ho difficoltà a vedere come la tua risposta risponde alla domanda.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.