2009-05-15 15 views
0

Der folgende Code ist der kleine Ausgangspunkt für einen neuen Weg (für mich) zum Schreiben und Verwalten von Code. Bevor ich einige Wochen verliere und am Ende wahrscheinlich feststelle, dass es sich um eine blöde Idee handelte, dachte ich, es wäre besser, hier erstmal "Stresstest" zu machen.Ist es eine gute Idee, das Factory-Methodenentwurfsmuster zum Verwalten verschiedener Klassenversionen in C# zu verwenden?

Also hier ist die Idee. Jedes Mal, wenn Abhängigkeiten vom Typ vorhanden sind, wenn Client (Envoker) -Klassen Server verwenden (Klasse, die einige Dienste bereitstellt - in dem folgenden Beispiel Controller genannt), verwendet der Client eine statische Methode zu einem "Stub" mit einem Namen, der generisch genug ist Dieser Name müsste nicht geändert werden - zum Beispiel CreateDynamicTextBox() oder RunProcedureGetDataSet() und übergibt ein Konfigurationsobjekt, nach dem die Factory die angeforderte Version der Server-Klasse bereitstellt, also jedes Mal, wenn eine ausreichend stabile Version von Server vorhanden ist wenn neue Funktionalitäten hinzugefügt werden müssen (oder die Logik davon sollte geändert werden) und neue Server-Klassenversion wird geschrieben. Der vorgeschlagene Vorteil ist die Bewahrung des Flusses über die generische Methode und die Weitergabe des "setting" -Objekts.

Ist das eine schlechte Idee?! Wenn ja warum? Alles positiv in diesem Ansatz?

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 

Antwort

1

Es ist in Ordnung, das Fabrikmuster für so etwas zu verwenden. FactoryMethod() sollte jedoch der Ort sein, an dem sich die Logik befindet, um auszuwählen, welche Klasse instanziiert werden soll. Wenn FactoryMethod() den Typ Controller zurückgibt, gibt es keinen Grund, das zurückgegebene Objekt zu konvertieren.

Ihre RunMethod() zu so etwas wie dies ändern würde ...

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

Und Ihre FactoryMethod() würde wie folgt aussehen ...

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

Danke, Jon. Ich musste den Code einfügen, den du als Antwort meintest (Es sollte Syntaxhervorhebung auch in Kommentaren geben; (und mindestens 1000 Zeilen Leerzeichen;) –

0

Danke, Jon. Ich denke, du meintest die Implementierung, die ich unten schreibe (natürlich werde ich das nicht als Antwort akzeptieren!). Ja, es scheint einfacher zu sein als mein Code oben mit der seltsamen statischen Methode. Trotzdem, ist das die gleiche "Funktionalität"? Wenn diese Art von "Hot-Swapping" funktioniert, wie oft oder in welcher Art von Situationen könnte es verwendet werden (ich denke über dynamische Steuerelemente Generation und dynamische Auswahl von Datenbank-Anbietern).

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

Nun, ich habe versehentlich CFSetter.Third in der switch-Anweisung weggelassen ... aber ja Dies ist die gleiche Funktionalität: Main() weiß nicht, welcher Typ von Controller instanziiert werden soll (und ist auch nicht wichtig) .Das ist der Zweck der ControllerFactory.Sie können weiterhin verschiedene mögliche Klassen hinzufügen, die abgeleitet sind Controller zum Ändern der Scream() -Funktionalität und Ihr Code in Main() müssen sich niemals ändern Die von Ihnen aufgeführten Situationen sind für die Verwendung dieses Mustertyps sehr sinnvoll. –

Verwandte Themen