Domanda Metodi factory statici vs costruttori di istanze (normali)?


In una lingua in cui entrambi sono disponibili, preferiresti vedere un costruttore di istanze o un metodo statico che restituisce un'istanza?

Ad esempio, se stai creando un String da un char[]:

  1. String.FromCharacters(chars);

  2. new String(chars);


44
2017-10-11 19:41


origine


risposte:


In Efficace Java, 2a edizione, Joshua Bloch certamente consiglia il primo. Ci sono alcuni motivi che posso ricordare, e senza dubbio alcuni non posso:

  • Puoi dare al metodo un nome significativo. Se hai due modi di costruire un'istanza che accettano entrambi un int, ma hanno significati diversi per quell'int, l'uso di un metodo normale rende il codice chiamante molto più leggibile.
  • Un corollario del primo: puoi avere diversi metodi di fabbrica con lo stesso elenco di parametri
  • È possibile restituire null per i casi di "potenziale attesa" mentre un costruttore lo farà sempre o restituire un valore o generare un'eccezione
  • Puoi restituire un tipo diverso da dichiarato (ad esempio restituire una classe derivata)
  • È possibile utilizzarlo come factory per potenzialmente restituire un riferimento allo stesso oggetto più volte

I lati negativi:

  • Non è così idiota, al momento - gli sviluppatori sono più abituati a vedere "nuovi"
  • Se vedi "nuovo" tu conoscere stai ricevendo una nuova istanza (modulo il stranezza che ho menzionato di recente)
  • È necessario creare costruttori appropriati per sottoclassi
  • In C # 3, le chiamate del costruttore sono in grado di impostare campi / proprietà in modo compatto con le espressioni di inizializzazione dell'oggetto; la funzione non si applica alle chiamate al metodo statico

51
2017-10-11 19:48



Scrivo un costruttore quando la creazione dell'istanza non ha effetti collaterali, vale a dire quando l'unica cosa che sta facendo il costruttore è l'inizializzazione delle proprietà. Scrivo un metodo statico (e rendi privato il costruttore) se la creazione dell'istanza fa qualcosa che normalmente non ti aspetti da un costruttore.

Per esempio:

public class Foo
{
   private Foo() { }

   private static List<Foo> FooList = new List<Foo>();
   public static Foo CreateFoo()
   {
      Foo f = new Foo();
      FooList.Add(f);
      return f;
   }
}

Perché aderisco a questa convenzione, se vedo

Foo f = Foo.CreateFoo();
Bar b = new Bar();

mentre leggo il mio codice, ho una serie di aspettative molto diverse su ciò che ciascuna di queste due linee sta facendo. Quel codice non mi dice che cosa rende la creazione di Foo diversa dalla creazione di una barra, ma mi sta dicendo che devo guardare.


20
2017-10-11 20:06



Se il tuo oggetto è immutabile, potresti essere in grado di utilizzare il metodo statico per restituire oggetti memorizzati nella cache e salvare te stesso l'allocazione e l'elaborazione della memoria.


9
2017-10-11 20:05



Recentemente ho lavorato a un'API pubblica e sono stato agonizzante per la scelta dei metodi di factory statici rispetto al costruttore. In alcuni casi, i metodi di produzione statici hanno sicuramente senso, ma in altri non è così chiaro e sono incerto se la coerenza con il resto dell'API sia una ragione sufficiente per includerli sui costruttori.

Ad ogni modo, mi sono imbattuto in un citazione da un'intervista di Bill-Venners con Josh Bloch che ho trovato utile:

Quando scrivi un corso, puoi farlo   scorrete la lista del mio libro del   vantaggi delle fabbriche statiche finite   costruttori pubblici. Se lo trovi   un numero significativo di quelli   i vantaggi effettivamente si applicano al tuo   caso, allora dovresti andare con il   fabbriche statiche. Altrimenti dovresti   vai con i costruttori.

Alcune persone sono state deluse da trovare   quel consiglio nel mio libro. Lo leggono   e disse: "Hai discusso così fortemente   per le fabbriche statiche pubbliche che noi   dovrebbero semplicemente usarli per impostazione predefinita. "I   pensa l'unico vero svantaggio in   fare così è che è un po '   sconcertante per le persone che vengono utilizzate   usare i costruttori per creare il loro   oggetti. E suppongo che fornisca a   un po 'meno di uno spunto visivo nel   programma. (Non vedi il nuovo   parola chiave.) Inoltre è un po 'di più   difficile trovare fabbriche statiche in   la documentazione, perché Javadoc   raggruppa tutti i costruttori insieme.   Ma direi che tutti dovrebbero   considera le fabbriche statiche tutto il   tempo e usali quando sono   adeguata.

Avendo letto quella citazione, e lo studio menzionato da Uri*, Mi sento incline a sbagliare a favore dei costruttori a meno che non ci siano validi motivi per fare altrimenti. Penso che un metodo statico di fabbrica senza una buona causa sia probabilmente solo una complessità non necessaria e un'eccessiva ingegnerizzazione. Anche se domani potrei cambiare idea di nuovo ...

* Sfortunatamente questo studio si è concentrato meno sui metodi di factory statici e più sul pattern factory (dove esiste un oggetto factory separato per creare nuove istanze), quindi non sono sicuro che si possa davvero trarre la conclusione che i metodi statici di fabbrica confondono molti programmatori. Sebbene lo studio mi abbia dato l'impressione che lo farebbero spesso.


9
2018-06-15 10:59



C'è un articolo di ICSE'07 che ha studiato l'usabilità dei costruttori rispetto ai modelli di fabbrica. Mentre preferisco i modelli di fabbrica, lo studio ha mostrato che gli sviluppatori erano più lenti nel trovare il metodo corretto di fabbrica.

http://www.cs.cmu.edu/~NatProg/papers/Ellis2007FactoryUsability.pdf


7
2017-10-11 19:54



Metodo statico Quindi è possibile restituire un valore nullo, anziché generare un'eccezione (a meno che non sia un tipo di riferimento)


3
2017-10-11 19:44



Preferisco il costruttore di istanze, solo perché ha più senso per me, e c'è meno ambiguità potenziale con quello che stai cercando di esprimere (cioè: cosa succede se FromCharacters è un metodo che prende un singolo carattere). Certamente soggettivo, però.


2
2017-10-11 19:46