2016-07-29 16 views
0

Ich versuche, eine Fabrik zu machen, die Klassen erstellt, die die gleiche Basisklasse (oder Schnittstelle) verwenden, aber die Betonfabriken benötigen unterschiedliche Parametersätze. Wenn ich das Gefühl habe, dass ich etwas falsch mache, da diese verschiedenen Enums zusätzlichen Code erfordern. Könnte das besser gemacht werden?Factory-Muster-Implementierungen mit verschiedenen Parametern

Klassen erstellt werden:

public interface IShapeData {} 

public abstract class ShapeDataWithCorners : IShapeData 
{ 
    public double Width { get; set; } 
} 

class Square : ShapeDataWithCorners {} 

class Rectangle : ShapeDataWithCorners 
{ 
    public double Height { get; set; } 
} 

class Circle : IShapeData 
{ 
    public double Radius { get; set; } 
} 

class Oval : IShapeData 
{ 
    public double Radius1 { get; set; } 
    public double Radius2 { get; set; } 
} 

Fabriken:

public enum RoundShapeTypes 
{ 
    Circle, 
    Oval 
} 

public enum CornerShapeTypes 
{ 
    Square, 
    Rectangle 
} 

public class RoundShapeDataFactory : IShapeDataFactory 
{ 
    private readonly RoundShapeTypes m_shapeType; 

    public RoundShapeDataFactory (RoundShapeTypes shapeType) 
    { 
     m_shapeType = shapeType; 
    } 

    public IShapeData CreateShapeData() 
    { 
     switch (m_shapeType) 
     { 
      case RoundShapeTypes.Circle: 
       return new Circle(); 
      case RoundShapeTypes.Oval: 
       return new Oval(); 
     } 
    } 
} 

public class CornerShapeDataFactory : IShapeDataFactory 
{ 
    private readonly CornerShapeTypes m_shapeType; 

    public CornerShapeDataFactory (CornerShapeTypes shapeType) 
    { 
     m_shapeType = shapeType; 
    } 

    public IShapeData CreateShapeData() 
    { 
     switch (m_shapeType) 
     { 
      case CornerShapeTypes.Square: 
       return new Square(); 
      case CornerShapeTypes.Rectangle: 
       return new Rectangle(); 
     } 
    } 
} 

Klassen, die das Werk nennen:

public class RoundShapeManager 
{ 
    public IShapeData CurrentShapeData{get; set; } 

    public void SetShapeType (RoundShapeTypes shapeType) 
    { 
     RoundShapeDataFactory factory = new RoundShapeDataFactory (shapeType); 
     CurrentShapeData = factory.CreateShapeData(); 
    } 
} 

public class CornerShapeManager 
{ 
    public IShapeData CurrentShapeData {get; set; } 

    public void SetShapeType (CornerShapeTypes shapeType) 
    { 
     CornerShapeDataFactory factory = new CornerShapeDataFactory (shapeType); 
     CurrentShapeData = factory.CreateShapeData(); 
    } 
} 

Diese "Manager" sind tatsächlich WPF Viewmodels, die ändern können ihr Vertreter zeigte Daten zur Laufzeit an. Ich habe den Viewmodel-spezifischen Code der Kürze halber entfernt.

+0

Dies könnte eine gute Frage für [codereview.se] – null

+1

Ich habe nur den Kommentar, nicht die enge Abstimmung verlassen. Da die Schlussabstimmung für "zu breit" ist, liegt das wahrscheinlich daran, dass Ihre Frage offen ist, was für CR gilt, aber nicht für SO (siehe die Tabelle in der akzeptierten Antwort in der Metafrage, mit der Sie verbunden sind). Im selben Absatz wie die von Ihnen zitierte Zeile: "* Stimmen Sie stattdessen ab, um zu weit oder überwiegend auf Meinung zu schließen. *" – null

Antwort

1

Sie können es so weit reduzieren:

public interface IShapeData { } 

public abstract class ShapeDataWithCorners : IShapeData 
{ 
    public double Width { get; set; } 
} 

public class Square : ShapeDataWithCorners { } 

public class Rectangle : ShapeDataWithCorners 
{ 
    public double Height { get; set; } 
} 

public class Circle : IShapeData 
{ 
    public double Radius { get; set; } 
} 

public class Oval : IShapeData 
{ 
    public double Radius1 { get; set; } 
    public double Radius2 { get; set; } 
} 

public enum ShapeType 
{ 
    Circle, 
    Oval, 
    Square, 
    Rectangle 
} 

public interface IShapeDataFactory 
{ 
    IShapeData CreateShapeData(ShapeType shapeType); 
} 

public class ShapeDataFactory : IShapeDataFactory 
{ 
    public IShapeData CreateShapeData(ShapeType shapeType) 
    { 
     switch (shapeType) 
     { 
      case ShapeType.Circle: 
       return new Square(); 
      case ShapeType.Oval: 
       return new Oval(); 
      case ShapeType.Rectangle: 
       return new Rectangle(); 
      case ShapeType.Square: 
       return new Square(); 
      default: 
       throw new ArgumentException("invalid shape type"); 
     } 
    } 
} 

So eine Fabrik, eine Enum mit allen Formtypen, und Sie können einen einzelnen Manager haben, die im Grunde tut dies:

IShapeDataFactory s = new ShapeDataFactory(); 
IShapeData temp = s.CreateShapeData(ShapeType.Square); 
+0

Die separaten Aufzählungen sollten verwendet werden, um gültige Optionen in der Benutzeroberfläche darzustellen. Ich nehme an, dass eine Konvertierung auf der UI-Seite stattfinden könnte, um die einzelne Enumeration beim Aufruf der Factory zu verwenden. – kbeal2k

+0

Das macht Sinn. Die Parameter, die der Fabrik mitteilen, welcher Typ zurückgegeben werden soll, gehören in die Create-Methode (wie in der Antwort gezeigt), nicht in den Konstruktor für die Factory. Wenn die Klasse wissen muss, welche Konstruktorargumente an die Factory übergeben werden sollen, ist die Klasse für das Erstellen der Factory verantwortlich, was den Zweck der Factory vereitelt. –

+0

@ScottHannen - vereinbart. Die Verantwortung liegt nur bei der Fabrik und nicht bei der Verpackung in der Fabrik. – Ric

Verwandte Themen