Seguendo gli schemi di progettazione proposti dalla Gang of Four , puoi utilizzare Factory Abstract modello per creare un'istanza delle diverse implementazioni. Ad esempio:
abstract class Parent {
// some abstract behaviour
}
interface ParentFactory {
Parent Make();
}
class Impl1 : Parent {
// some concrete behaviour
}
class Impl1Factory : ParentFactory {
public Parent Make() {
return new Impl1();
}
}
class Impl2 : Parent {
// some concrete behaviour
}
class Impl2Factory : ParentFactory {
public Parent Make() {
return new Impl2();
}
}
Questo isolerà le responsabilità di creare istanze di ogni sottotipo nelle proprie classi, che possono essere collocate in spazi dei nomi diversi o anche librerie separate, consentendo di apportare modifiche isolate ogni volta che è necessario.
Ma solo il modello astratto di fabbrica da solo non è molto facile da usare, quindi una pratica comune è creare una sorta di registro, in cui il resto del sistema può richiedere una specifica implementazione. Un esempio potrebbe essere quello di utilizzare qualcosa di simile al modello Localizzatore di servizio , in questo modo:
class ParentFactories {
private Dictionary<string, ParentFactory> factories;
// constructor and such - probably private and following the Singleton pattern
public void Register(string key, ParentFactory factory) {
factories.Add(key, factory);
}
public Parent Make(string key) {
return dictionary[key].Make();
}
}
Nell'esempio precedente, ho usato un string
per key
, ma questo era solo per mostrare come registrare una fabbrica nel localizzatore usando un Dictionary
, che è l'approccio comune. Puoi usare tutto ciò che è rilevante per le tue regole di business, inclusi i tuoi oggetti come una sorta di identificatore / oggetto di query che dice al locatore quale implementazione è richiesta.
In ogni caso, il punto di un oggetto simile a Locator è di consentire al sistema di aggiungere e / o rimuovere diversi sistemi di implementazione ParentFactory
in fase di runtime. Seguendo questo schema, puoi separare le implementazioni concrete della tua classe astratta in diversi moduli dell'applicazione, e fare in modo che ogni modulo registri le sue implementazioni sul localizzatore all'avvio.