2009-05-15 4 views
0

Le code ci-dessous est le petit point de départ pour une nouvelle façon (pour moi) d'écrire et de gérer le code. Avant de perdre quelques semaines et probablement dire à la fin que oui, c'était une idée stupide, je pensais qu'il serait préférable de "stress test" ici d'abord.Est-ce une bonne idée d'utiliser un modèle de conception de méthode d'usine pour gérer différentes versions de classe en C#?

Voici donc l'idée. Chaque fois qu'il existe des dépendances du type lorsque les classes Client (Envoker) utilisent le Serveur (classe fournissant certains services - appelé Contrôleur dans l'exemple ci-dessous), le Client utiliserait une méthode statique à un "stub" avec un nom suffisamment générique pour que ce nom ne devrait pas changer - par exemple CreateDynamicTextBox() ou RunProcedureGetDataSet() et passera un objet de configuration selon lequel l'usine fournira la version demandée de la classe Server, donc chaque fois qu'il existe une version assez stable du serveur lorsque de nouvelles fonctionnalités doivent y être ajoutées (ou que sa logique doit être modifiée) et que la nouvelle version de la classe Serveur sera écrite. Le bénéfice proposé sera la préservation du flux via la méthode générique et le passage de l'objet "setting".

Est-ce une mauvaise idée?! Si oui, pourquoi? Quelque chose de positif dans cette approche?!

using System; 


namespace ControllerFactory 
{ 
    class ClientEnvoker 
    { 
    static void Main (string[] args) 
    { 

     Console.WriteLine (" START "); 
     ClientEnvoker objClientEnvoker = new ClientEnvoker(); 

     ControllerFactory objControllerFactory = new ControllerFactory(); 

     Console.WriteLine (" RUN METHOD 1 WITH CONTROLLER 1 WITH CONFIG 1 "); 
     objControllerFactory.GenericMethodName (ControllerFactory.CFSetter.First); 

     Console.WriteLine (" RUN METHOD 2 WITH CONTROLLER 2 WITH CONFIG 2 "); 
     objControllerFactory.GenericMethodName (ControllerFactory.CFSetter.Second); 

     Console.WriteLine (" RUN METHOD 3 WITH CONTROLLER 3 WITH CONFIG 3 "); 
     objControllerFactory.GenericMethodName (ControllerFactory.CFSetter.Second); 

     Console.WriteLine (" END HIT A KEY TO EXIT "); 
     Console.ReadLine(); 

    } //eof method 

    } //eof class 


    class ControllerFactory 
    { 
    public enum CFSetter : int 
    { 
     First = 1, 
     Second = 2 , 
     Third = 3 
    } 

    public void GenericMethodName (CFSetter objCFSetter) 
    { 
     Controller c = this.FactoryMethod (objCFSetter); 
     c.ConcreteMethod(); 
    } //eof method 

    public Controller FactoryMethod (CFSetter objCFSetter) 
    { 
     Controller controllerReturn = null; 
     switch (objCFSetter) 
     { 
     case CFSetter.First: 
      controllerReturn = new Controller1(); 
      break; 
     case CFSetter.Second: 
      controllerReturn = new Controller2(); 
      break; 
     case CFSetter.Third: 
      controllerReturn = new Controller3(); 
      break; 
     default: 
      controllerReturn = new Controller1(); 
      break; 
     } 
     return controllerReturn; 
    } 

    } //eof class 

    #region Controllers 
    public abstract class Controller 
    { 
    public abstract void ConcreteMethod(); 
    } 


    public class Controller1 : Controller 
    { 

    public override void ConcreteMethod() 
    { 
     Console.WriteLine ("Controller1 screams according to version 1 logic"); 
    } 
    } //eof class 

    public class Controller2 : Controller 
    { 

    public override void ConcreteMethod() 
    { 
     Console.WriteLine ("Controller2 screams according to version 2 logic"); 
    } 
    } //eof class 


    public class Controller3 : Controller 
    { 

    public override void ConcreteMethod() 
    { 
     Console.WriteLine ("Controller3 screams according to version 3 logic"); 
    } 
    } //eof class 

    #endregion Controllers 



} //eof namespace 

Répondre

1

Il est bon d'utiliser le modèle d'usine pour quelque chose comme ceci. Cependant, FactoryMethod() devrait être où la logique réside pour choisir quelle classe instancier. En outre, si FactoryMethod() renvoie le type Controller, il n'y a aucune raison de lancer l'objet renvoyé.

Votre RunMethod() changerait quelque chose comme ça ...

ControllerFactory cf = new ControllerFactory(); 
Controller c = cf.FactoryMethod(objCFSetter); 
c.Scream(); 

Et votre FactoryMethod() ressemblerait à ceci ...

Controller controllerReturn = null; 
switch (objCFSetter) { 
    case CFSetter.First: 
     controllerReturn = new Controller1(); 
     break; 
    case CFSetter.Second: 
     controllerReturn = new Controller2(); 
     break; 
    default: 
     controllerReturn = new Controller1(); 
     break; 
} 
return controllerReturn; 
+0

Merci, Jon. Je devais coller le code que vous vouliez dire comme réponse (il devrait y avoir une coloration syntaxique dans les commentaires aussi (et au moins 1000 lignes d'espace;) –

0

Merci, Jon. Je pense que vous vouliez dire la mise en œuvre que je publie ci-dessous (bien sûr, ne va pas l'accepter comme la réponse!). Oui, il semble être plus simple que mon code ci-dessus avec l'étrange méthode statique. Pourtant, est-ce la même "fonctionnalité"? Si ce type de "hot-swapping" fonctionne à quelle fréquence, ou dans quel type de situations il peut être utilisé (je pense à la génération de commandes dynamiques et au choix dynamique des fournisseurs de bases de données).

using System; 


namespace ControllerFactory 
{ 
    class ClientEnvoker 
    { 
    static void Main (string[] args) 
    { 

     Console.WriteLine (" START "); 
     ClientEnvoker objClientEnvoker = new ClientEnvoker(); 

     ControllerFactory cf = new ControllerFactory(); 

     Console.WriteLine (" RUN METHOD 1 WITH CONTROLLER 1 WITH CONFIG 1 "); 
     cf.RunMethod (ControllerFactory.CFSetter.First); 

     Console.WriteLine (" RUN METHOD 2 WITH CONTROLLER 1 WITH CONFIG 2 "); 
     cf.RunMethod (ControllerFactory.CFSetter.Second); 


     Console.WriteLine (" END HIT A KEY TO EXIT "); 
     Console.ReadLine(); 

    } //eof method 

    } //eof class 


    class ControllerFactory 
    { 
    public enum CFSetter : int 
    { 
     First = 1, 
     Second = 2 
    } 

    public void RunMethod (CFSetter objCFSetter) 
    { 
     Controller c = this.FactoryMethod (objCFSetter); 
     c.Scream(); 
    } //eof method 

    public Controller FactoryMethod (CFSetter objCFSetter) 
    { 
     Controller controllerReturn = null; 
     switch (objCFSetter) 
     { 
     case CFSetter.First: 
      controllerReturn = new Controller1(); 
      break; 
     case CFSetter.Second: 
      controllerReturn = new Controller2(); 
      break; 
     default: 
      controllerReturn = new Controller1(); 
      break; 
     } 
     return controllerReturn; 
    } 

    } //eof class 

    #region Controllers 
    public abstract class Controller 
    { 
    public abstract void Scream(); 
    } 


    public class Controller1 : Controller 
    { 

    public override void Scream() 
    { 
     Console.WriteLine ("Controller1 screams according to version 1 logic"); 
    } 
    } //eof class 

    public class Controller2 : Controller 
    { 

    public override void Scream() 
    { 
     Console.WriteLine ("Controller2 screams according to version 2 logic"); 
    } 
    } //eof class 

    #endregion Controllers 



} //eof namespace 
+0

Eh bien, j'ai oublié accidentellement CFSetter.Tird dans l'instruction switch ... mais oui En fait, Main() ne sait pas quel type de contrôleur va être instancié (et ne s'en soucie pas) .C'est le but de la ControllerFactory Vous pouvez continuer à ajouter différentes classes possibles dérivées de Le contrôleur pour modifier la fonctionnalité Scream() et votre code dans Main() ne devront jamais changer.Les situations que vous avez énumérées sont parfaitement adaptées à l'utilisation de ce type de modèle. –

Questions connexes