Valides Dreieck erzeugen

temi

Top Contributor
Hallo zusammen,

aufgrund einer vor Kurzem geführten Diskussion, wie ein korrektes Dreieck erzeugt werden kann (sollte), habe ich mir auch Gedanken zu dem Thema gemacht. Das hat keinen tieferen Hintergrund und ist eher theoretischer Natur. Ich bin ja schließlich auch noch Anfänger 😉

Eine bereits angesprochene Lösung war, der Klasse "Dreieck" mehrere Konstruktoren zu geben, um Dreiecke z.B. mit drei Seiten, zwei Seiten und Winkel oder einer Seite und zwei Winkeln zu erzeugen. Ergänzen, könnte man jetzt noch Konstruktoren mit Fläche und Seiten (und/oder Winkeln) usw.

Das finde ich jetzt aber auch nicht so richtig flexibel, da habe ich mich an CAD erinnert, wo es den Begriff der Constraints gibt, also geometrische Grenzen, die ein Objekt einhalten muss.

Mein Ansatz wäre demnach eine sehr einfache Klasse "Dreieck", mit einem simplen "drei bekannte Seiten Konstruktor" und eine Fabrik-Klasse. Die "Idee" ist, dieser Klasse solange Werte für Dreiecksparameter zu geben (Seitenlängen, Winkel, Fläche, Umfang) bis ein gültiges Dreieck erzeugt werden kann. Ungefähr so:
Java:
TriangleFactory factory = new TriangleFactory();

factory.setSide(SIDE.a, 10);
factory.setSide(SIDE.b, 10);
factory.setAngle(ANGLE.alpha, 60);
// validate and then
Triangle triangle = factory.getInstance();

Damit ist allerdings das "Wissen" über die Erzeugung (und auch einiges an Berechnung) nicht in der Klasse Dreieck, sondern in der Fabrik. Die Klasse Dreieck hat Berechnungsmethoden für alle Winkel, Fläche und Umfang (was leider ggf. doppelten Code mit der Fabrik bedeuten kann). Denkbar wäre es das alles in der Klasse Dreieck zu veranstalten, aber dann würde durch den Konstruktor zunächst ein ungültiges Dreieck erzeugt, was mich nicht überzeugt.

Ist das vom Design her in Ordnung oder gibt es bessere Ansätze?
 
Man könnte da mit Builder-Pattern und Method-Chaining arbeiten.
Kommt deinem Factory-Ansatz nah, lässt sich aber manchmal mehr mit erreichen und ist besser zu benutzen.

Java:
a(10).b(10).alpha(60)

Möglicherweise lässt sich da mit viel Trickserei mit Interfaces noch mehr erreichen, z.B. sicher stellen, dass mindestens eine Länge angegeben wird und danach die entsprechend nötigen anderen Werte.




Ansonsten u.U. der Factory-Method einfach eine "Menge von Werten" übergeben und intern wird dann einfach für die Werte die passend Formel rausgesucht und das passende Dreieck ausgespuckt, z.B. mit chain of responsibility.
Benutzung wäre etwa so:
Java:
triangle(a(10), b(10), alpha(60)); //a,b,alpha entsprechende statische Methoden für Seiten/Winkel
Könnte man u.U. auch wieder mit entsprechenden Typen arbeiten (ist aber vllt auch nicht umsetzbar?)
 
Method-Chaining halte ich für eine gute Idee. 😎
Java:
TriangleBuilder.a(10).b(10).alpha(60).tryGetInstance();

Zwischenfrage: Wird das auch Fluent-Interface genannt, oder ist das was anderes?

Wegen dupliziertem Code wäre es möglicherweise sinnvoll eine zusätzliche Klasse mit den Berechnungen zum Dreieck zu erstellen und sowohl aus der Factory (oder Builder) und auch aus Triangle auf die benötigten Methoden zuzugreifen. Oder das Dreieck erhält durch den Builder bereits alle berechneten Werte übergeben und dient nur als POJO.
 
Ja die Methode heißt auch Fluent-Interface. Persönlich finde ich diese Idee auch die beste. Eine andere, die mir noch eingefallen ist, ist folgende. Ein Interface oder abstrakte Klasse Dreieck, die Methoden hat wie getA, getB, getC, dann noch z.b. getPerimeter, die schon eine default-Implementierung besitzt mit "return getA() + getB() + getC()" usw. So nun kommt der Clou, es wird nun für jede Möglichkeit, ein Dreieck zu bilden eine Klasse erstellt. Zum Beispiel für SWS (also Seite-Winkel-Seite) gibt es eine Klasse, die auch nur diese drei Werte speichert. Die Methode getC berechnet dann die dritte Seite, ohne sie zu speichern. Zusätzlich könnte man noch abstrakte Klassen für bestimmte Eigenschaften schreiben, wie GleichseitigesDreieck, RechtwinkligesDreieck ect., die weitere Methoden default implementieren.
Wenn ich jetzt so drüber nachdenke, könnte man dies sogar mit Fluent-Interfaces verbinden. Die Kette stopt immer bei einer dieser Klasse, jenachdem welchen Weg man geht.
 
Zuletzt bearbeitet:
Wegen dupliziertem Code wäre es möglicherweise sinnvoll eine zusätzliche Klasse mit den Berechnungen zum Dreieck zu erstellen und sowohl aus der Factory (oder Builder) und auch aus Triangle auf die benötigten Methoden zuzugreifen.

Naja, der Code zum Berechnen eines gültigen Dreieckes aus gegebenen Werten und der, um aus einem gültigem Dreieck die anderen Wert zu berechnen, hat nur im mathematischen Sinne was miteinander zu tun. Wirklich doppelter Code wird da nicht anfallen, von daher kann man das super trennen 😉


Oder das Dreieck erhält durch den Builder bereits alle berechneten Werte übergeben und dient nur als POJO.
POJO ist so ein Dreieck hoffentlich in jedem Fall ;P das sagt im wesentlichen nicht mehr aus, als das eine Klasse nicht irgendwelche speziellen technischen Konventionen, sondern nur fachliche einhält 😉

Zwischenfrage: Wird das auch Fluent-Interface genannt, oder ist das was anderes?
Kommt dem nah, wobei man das vermutlich noch "sprechender" schreiben könnte.
 

Zurück
Oben