12

Ho letto Java efficace di Joshua Bloch e finora è all'altezza della sua reputazione. Il primo elemento costituisce un caso convincente per i metodi di produzione statica su . Tanto che ho iniziato a mettere in discussione la validità dei buoni vecchi costruttori :).Abbiamo mai bisogno di preferire i costruttori rispetto ai metodi statici di fabbrica? Se sì, quando?

i vantaggi/svantaggi del libro sono riassunte di seguito:

Vantaggi:

  1. Hanno nomi!
  2. Abbiamo totale controllo esempio (Singletons, prestazioni, ecc)
  3. Essi possono restituire un sottotipo/interfaccia
  4. compilatore può fornire inferenza

Svantaggi:

  1. Le classi private non possono essere sottoclasse
  2. Non si distinguono nella documentazione come costruttore s do

Il primo svantaggio può effettivamente essere una buona cosa (come menzionato nel libro). Il secondo, penso sia solo uno svantaggio minore e può essere risolto facilmente con le prossime versioni java (annotazioni per javadoc ecc.)

Sembra che alla fine i metodi di fabbrica abbiano quasi tutti i vantaggi dei costruttori, molti molti altri vantaggi e nessun vero svantaggio!

Quindi, la mia domanda è sostanzialmente in tre parti:

  1. E 'buona prassi utilizzare sempre metodi di fabbrica statici di default sopra i costruttori?
  2. È mai giustificato utilizzare i costruttori?
  3. Perché i linguaggi orientati agli oggetti non forniscono supporto a livello di lingua per le fabbriche?

Nota: Ci sono due domande simili: When to use a Constructor and when to use getInstance() method (static factory methods)? e Creation of Objects: Constructors or Static Factory Methods. Tuttavia, le risposte o forniscono semplicemente l'elenco sopra riportato o reiterano la logica dietro i metodi statici di fabbrica di cui sono già a conoscenza.

+0

Inoltre, apparentemente le fabbriche hanno anche vantaggi per la sicurezza del filo rispetto ai costruttori secondo [questo] (http://madpropellerhead.com/random/20100328-java-final-fields-are-not-as-final-as- potresti pensare). – MadChuckle

+0

Ho letto l'articolo di riferimento, ma sono giunto alla conclusione opposta dell'autore ... :-) Vedo cosa viene indicato, ma non sono d'accordo. Forse ha a che fare con i casi d'uso specifici che ognuno di noi vede normalmente durante la codifica. –

+0

@BrianKnoblauch, non sono esperto di concorrenza, quindi ti prendo in parola perché gli esempi sembrano un po 'forzati :) – MadChuckle

risposta

7

Le fabbriche statiche devono ancora chiamare un costruttore alla fine. È possibile spostare la maggior parte delle funzionalità nel factory statico, ma non è possibile evitare di utilizzare un costruttore.

D'altra parte per casi semplici, si può avere solo un costruttore senza avere una fabbrica statica.

I costruttori sono l'unico modo per impostare i campi finali, che IMHO sono preferibili ai campi non finali.

È possibile utilizzare i costruttori possono nelle sottoclassi. Non è possibile utilizzare le fabbriche statiche per una sottoclasse.

Se si dispone di una buona infrastruttura di dipendenza per le dipendenze di un componente, è possibile che le fabbriche statiche non aggiungano molto.

+0

Ovviamente le fabbriche usano i costruttori dietro le quinte ed è per questo che ho incluso la terza domanda. E le fabbriche possono impostare i campi finali usando i costruttori sicuri. Non capisco la restrizione delle sottoclassi che menzioni; cura di elaborare? – MadChuckle

+0

Ok, sembra che tu parli del primo svantaggio lì; ma forse possiamo fornire costruttori "oltre" alle fabbriche per quello? – MadChuckle

+0

"I costruttori sono l'unico modo per impostare i campi finali, che IMHO sono preferibili ai campi non finali." Proprio qui c'è la grande ragione. I metodi di produzione statici consentono di tracciare un percorso che rende difficile la filettatura. I campi finali sono un buon inizio verso l'immutabilità (forzata) e la cordialità. In questo mondo ormai multi-core, lo spostamento è tornato verso i costruttori e lontano dalle fabbriche. –

3

Mi piace il commento di una delle domande simili che hai evidenziato:

(Su come decidere se è necessario favorire un metodo factory per un costruttore),

"è necessario decidere che cosa' Se non vuoi che le persone chiamino il tuo costruttore (stai creando un singleton o una factory), o non ti dispiace (come in NumberFormat sopra, dove stanno inizializzando alcuni oggetti per comodità del chiamante) "

Per me, questo significa che è giustificato a utilizzare un costruttore, dove non è richiesto il metodo factory. Senza alcuna necessità di una fabbrica, rende il codice più difficile da seguire ("quale sottoclasse esatta viene restituita qui?")

+2

Attendi. Ma parte del punto è che il chiamante non dovrebbe _care_ quale esatta sottoclasse viene restituita, e puoi cambiare quale sottoclasse esatta viene restituita senza dover cambiare i chiamanti. –

+0

Vero, ma se quelle sottoclassi implementano quell'API in modi diversi, probabilmente dovrai sapere quale sottoclasse esatta viene restituita quando cerchi di rintracciare i problemi nel codice. In queste circostanze, trovo oscure le cose nei metodi di fabbrica. –

+0

@ Disco3: un metodo factory legittimo dovrebbe restituire qualcosa i cui metodi si comporteranno, dal punto di vista * del chiamante *, come la classe genitore, ma ciò non significa che il comportamento interno debba corrispondere. Ad esempio, se 'String' fosse internamente ereditabile, la concatenazione di stringhe quando uno o più caratteri superiori a 256 caratteri potrebbe restituire un oggetto' ConcatenatedString' che manterrebbe una matrice di riferimenti alle stringhe più piccole. Tutti i metodi di 'ConcatenatedString' darebbero lo stesso risultato di una stringa contenente tutti i caratteri degli originali, ma ... – supercat

3

Sono molto d'accordo con Josh Bloch qui, e rende il caso migliore di quanto avrei potuto, ma qui ci sono alcuni luoghi in cui le fabbriche statiche non sono appropriate:

  • Quando l'iniezione di dipendenza è più sensibile; I sistemi DI (certamente Guice) tendono a iniettare le cose attraverso i loro costruttori. In particolare, DI è appropriato quando ci si aspetta che i parametri del costruttore possano cambiare in futuro.
  • Quando si intende specificamente per le persone scrivere sottoclassi e si sta fornendo uno scheletro da implementare.
+0

Buoni punti! Sebbene i sistemi DI possano anche essere implementati dal modello di fabbrica con alcuni vantaggi (), sono tendenzialmente d'accordo con te su questo. – MadChuckle

+0

Mentre un sistema DI che conosce solo i costruttori sarà limitato all'utilizzo di costruttori e uno che si aspetta che i metodi statici di fabbrica con un nome particolare siano limitati a classi con un metodo di quel nome, i costruttori offrono particolari vantaggi dal punto di vista DI? I costruttori * pubblici * offrono vantaggi in termini di sottoclassi rispetto ai metodi di fabbrica (i costruttori certamente protetti sarebbero necessari per la sottoclasse). – supercat

0

I costruttori sono noiosi, sai esattamente dove cercarli, conosci il loro scopo, sono in qualche modo prevedibili. Sono lì per costruire l'oggetto stesso, non per fare lavori simili a Dio. Se stai facendo troppe cose che non hanno molto a che fare con la costruzione dell'oggetto sai che stai facendo qualcosa di sbagliato. E non è possibile "curarlo" semplicemente rinominando il metodo. Quindi tendono ad essere più focalizzati, "migliori" nella qualità del codice quando non si hanno sviluppatori top-of-the-line. (Quando hai questi ultimi i punti che ho menzionato non hanno importanza.)

Noioso. Facciamo qualcosa di più divertente e intellettuale impegnativo ...

Giusto per la cronaca: non trascuro i punti menzionati nella domanda e altre risposte, volevo solo aggiungere questo punto aggiuntivo.

Problemi correlati