Metodo statico di creazione: vantaggi e svantaggi rispetto ai costruttori


11

Quali sono i pro e i contro di avere metodi di creazione di oggetti statici rispetto ai costruttori?

class Foo {
  private Foo(object arg) { }

  public static Foo Create(object arg) {
    if (!ValidateParam(arg)) { return null; }
    return new Foo(arg);
  }
}

Pochi a cui riesco a pensare:

Professionisti:

  • Restituisce null invece di generare un'eccezione (denominala TryCreate). Ciò può rendere il codice più conciso e pulito sul lato client. I clienti si aspettano raramente che un costruttore fallisca.
  • Crea diversi tipi di oggetti con una semantica chiara, ad es. CreatFromName(String name)ECreateFromCsvLine(String csvLine)
  • Può restituire un oggetto memorizzato nella cache, se necessario, o un'implementazione derivata.

Contro:

  • Codice meno rilevabile, più difficile da sfogliare.
  • Alcuni modelli, come la serializzazione o la riflessione, sono più difficili (ad es. Activator<Foo>.CreateInstance())

1
È più lento. Devi comunque gestire il riferimento null.
Amir Rezaei,

1
@Amir Handling null is ( Foo x = Foo.TryCreate(); if (x == null) { ... }). La gestione di un'eccezione ctor è ( Foo x; try { x = new Foo(); } catch (SomeException e) { ... }). Quando si chiama un metodo normale, preferisco le eccezioni ai codici di errore, ma con la creazione di oggetti, TryCreatesembra più pulito.
dbkk,

Nella tua validazione faresti qualche tipo di controllo?
Amir Rezaei,

Per quanto riguarda il secondo Pro, "Crea diversi tipi di oggetti con una semantica chiara, ad esempio CreatFromName (String name) e CreateFromCsvLine (String csvLine)", potresti essere meglio creare Namee digitare CsvLine, piuttosto che esprimere i requisiti tramite i nomi dei metodi. Ciò consentirebbe di sovraccaricare Crea. L'uso di stringhe per entrambi potrebbe essere considerato come "ossessione primitiva" (supponendo che tu non abbia fatto questa scelta per motivi prestazionali noti). Scopri Object Calisthenics per un modo divertente di esplorarlo.
Bentayloruk,

Risposte:


7

Il più grande svantaggio dei " creatori " statici è probabilmente la limitazione dell'eredità. Se tu o l'utente della tua biblioteca derivate una classe dalla vostra Foo, allora Foo::Create()diventa praticamente inutile. Tutta la logica ivi definita dovrà essere riscritta nuovamente nell'ereditato Create().

Suggerirei un compromesso: definire un costruttore con una banale logica di inizializzazione di oggetti che non fallisce mai / getta, quindi definire i creatori con cache, costruzione alternativa ecc. Ciò lascia la possibilità di derivare e si beneficia dell'avere creatori per una determinata classe .


1
In pratica non è davvero un problema, perché la maggior parte delle classi non è progettata per essere ereditata (e quindi dovrebbe essere sigillata / finale). Se in seguito si desidera aprire la classe all'ereditarietà, è sempre possibile spostare qualsiasi logica di inizializzazione in un costruttore protetto.
Doval,

7

Creare è un metodo Factory. Quando ne sento la necessità, implemento il modello Factory e definisco un'interfaccia per rappresentare il contratto per la creazione dell'oggetto e una classe di implementazione, che viene quindi iniettata dove necessario. Ciò mantiene i vantaggi di spostare la responsabilità della creazione fuori dalla classe, ma evita (o almeno rende più ovvio) i limiti dell'esecuzione della creazione di oggetti al di fuori del costruttore della classe.

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.