Mi sono trovato a pensare a questo un po 'di recente (quindi trovando questa domanda) e mentre non ho una risposta ho pensato di condividere i miei pensieri.
- Costruttori idealmente 'deve solo impostare lo stato dell'oggetto, cioè: alcuni:
this.member = member;
A mio parere questo gioca bene con IOC, l'ereditarietà, i test e solo buon profumo.
Tuttavia sollevamento di carichi pesanti a volte è necessario in modo da quello che ho cercato di fare è:
- Passo nel sollevamento di carichi pesanti.
Ciò significa astrarre che il codice di inizializzazione di un'altra classe e passaggio che in. Questo è di solito forse se il sollevamento di carichi pesanti non è davvero il tuo oggetti responsabilità, così facendo questo in realtà refactors in codice più bello.
Se questo non è possibile ed è necessario inizializzare lo stato per la classe prima dell'utilizzo, aggiungere un metodo initialse.Ciò aggiunge la dipendenza temporale nel codice, ma questo non è necessariamente una cosa negativa soprattutto quando si usano contenitori IoC:
Say CarEngine
richiede un DrivingAssistComputer
, e le DrivingAssistComputer
deve fare inizializzazione pesante, vale a dire caricare tutti i parametri, i controlli condizioni atmosferiche, ecc. Un'altra cosa da notare è che CarEngine
non interagisce direttamente con lo DrivingAssistComputer
, ha solo bisogno che sia presente, facendo le sue cose sul lato. In effetti, il motore potrebbe non funzionare correttamente senza il DrivingAssistComputer
che fa la sua cosa in background (cambiando qualche stato da qualche parte). Se stiamo usando CIO allora abbiamo:
// Without initialise (i.e. initialisation done in computer constructor)
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// No need to reference computer as we dont really interact with it.
}
...
Quindi quello che abbiamo qui è una marcatura computer
come una dipendenza, ma in realtà non usarlo argomento del costruttore. Quindi questo è brutto, ma lascia aggiungere un metodo di inizializzazione:
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
this.injectors = injectors;
// This ofcourse could also be moved to CarEngine.Initialse
computer.Initialise();
}
...
Ancora non non è una classe coesa, ma almeno sappiamo che dipendiamo sul computer, anche se non stiamo interagendo direttamente con esso al di fuori del costruttore.
Un'altra opzione naturalmente è quello di avere un CarEngineFactory che fa:
CarEngine CreateEngine(FuelInjectors injectors) {
new DrivingAssistComputer().Initialise();
return new CarEngine(injectors);
}
...
Tuttavia, ritengo che le fabbriche e il CIO solo confondere la matrice quindi vorrei andare per la seconda opzione.
Mi piacerebbe sentire alcuni pensieri su questo.
Modifica 1: Un'altra opzione che ho perso sopra sta avendo il metodo di inizializzazione ma lo spostamento di questa invocazione al modulo di inizializzazione IoC. Quindi la creazione e l'inizializzazione sono ancora in qualche modo incapsulate.
Ben messo. In passato mi sono anche orientato verso l'uso dei metodi 'initialize()' sui costruttori quando non istanzia direttamente il tuo oggetto, come usare un pattern factory. Pensi che questa sia una considerazione rilevante? – Ray