2012-12-14 3 views
41

Ich versuche ein Factory-Muster in Java zu implementieren. Ich habe eine Klasse namens Shape, die Kreis und Dreieck erweitert. Das Problem ist, dass Shape-Konstruktor nur 2 Parameter bekommt, während Circle 3 Parameter bekommt und so ist Triangle (was ich nicht im Code-Abschnitt anzeigen werde, weil es mit Circle identisch ist). es zu zeigen, besser:Factory in Java, wenn konkrete Objekte verschiedene Konstruktorparameter annehmen

private interface ShapeFactory{ 
     public Shape create(int x, int y); 
    } 

    private class CircleFactory implements ShapeFactory{ 
     public Shape create(float radius, int x, int y){ //error 
      return new Circle(radius, x,y); 
     } 
    } 

Irgendwelche Ideen, wie dieses Problem zu lösen? Ich darf keine Eingaben von Benutzern innerhalb der Fabrik erhalten (muss von außen empfangen werden).

Danke!

+0

Warum möchten Sie eine Fabrik verwenden? Was versuchst du zu erreichen? – miniBill

+1

Dachte, es ist keine süße Lösung, Sie können zusätzliche Karte von konkreten Form spezifische Parameter übergeben. Außerdem: Ist es notwendig, den Radius bei der Erstellung anzugeben? Sie können bei der Erstellung einen Standardradius festlegen und dann nach dem Erstellen der Form den gewünschten Radius festlegen. – nidu

+0

Nun, ich dachte über diese Option nach, aber es widerspricht der Idee von Konstruktor ... – Jjang

Antwort

27

Sie haben zwei Möglichkeiten:

1) Abstract Factory:

RectangularShape extends Shape

RoundShape extends Shape

und RectangularShapeFactory und RoundShapeFactory

2) Builder (siehe auch Punkt 2 in Effective Java)

public Shape { 
    private final int x; 
    private final int y; 
    private final double radius; 

    private Shape(Builder builder) { 
     x = builder.x; 
     y = builder.y; 
     radius = builder.radius; 
    } 

    public static class Builder { 
     private final int x; 
     private final int y; 
     private double radius; 

     public Builder(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 

     public Builder radius(double radius) { 
      this.radius = radius; 
      return this; 
     } 

     public Shape build() { 
      return new Shape(this); 
     }  
    } 
} 

//in client code 

    Shape rectangle = new Shape.Builder(x,y).build(); 
    Shape circle = new Shape.Builder(x,y).radius(radiusValue).build(); 
+4

Abstract Factory würde dieses Problem nicht lösen. Alle 'ShapeFactory'-Implementierungen benötigen immer noch eine gemeinsame Schnittstelle. – jaco0646

+0

(2) Der Builder hier sieht aus wie nur implizite Service-Locator Anti-Pattern. – SerG

6

Was Sie versuchen, ist einfach unmöglich. Wenn die Konstruktorargumente unterschiedlich sind, muss der Clientcode eine andere Arbeit für eine Circle als für eine Square und Sie können dies nicht mit einheitlichen Code lösen. Wenn es neben der Arbeit mit den Konstruktorargumenten, die Ihrer Meinung nach in einer Fabrik passieren sollten, auch andere Arbeiten gibt, müssen Sie dies auf Ihre Frage veröffentlichen und die Schwierigkeit angeben, die Sie haben, wenn Sie diese gängige Code-Arbeit ausschließen.

5

Alle Ihre Implementierungen müssen die gleiche Anzahl von Argumenten haben. Sie haben dort Optionen

  • haben die Fabrik speichern die zusätzlichen Argumente, so dass Sie nur das Zentrum zum Beispiel benötigen.
  • haben die Fabrik alle Argumente, obwohl einige Fabriken einige von ihnen ignorieren.
  • haben ein Argument variabler Länge. z.B. "double ..." Das Problem dabei ist, dass der Anrufer wissen muss, was die Fabrik braucht, um den Zweck einer Fabrik zu vereiteln. MEINER BESCHEIDENEN MEINUNG NACH.
+0

Würden Sie vorschlagen, heute mit Option 2 zu gehen? –

+0

Nur die erste Option ist im richtigen Abstract Factory-Muster verfügbar. Eine andere Möglichkeit, eine Factory mit den beiden Methoden CreateTriangle und CreateCircule zu erstellen, scheint jedoch orthogonal zum OP-Ziel zu sein. – SerG

Verwandte Themen