Im Frühjahr wächst…der Baum

Hallo Spaß-Coder.

Weiter geht es mit unserer Reihe über Entwurfsmuster, heute mit einem weiteren Muster aus der Kategorie der Strukturmuster. Wir schauen uns in diesem Artikel den Kompositum (engl. Composite) an, der auch aus der Sammlung der Gang of Four stammt.

 

Kompo…was?

Kompositum (oder auch Teile-Ganzes genannt) ist ein einfaches Muster um Hierarchien von Objekten abzubilden. Ein simples Beispiel dazu ist eine Baumstruktur wie bei einem Menü, bei dem es einen Einstiegspunkt, darunter Untermenüs und darunter ggf. wiederum weitere Untermenüs gibt. Die Besonderheit bei diesem Muster ist, dass alle Bestandteile der Hierarchie – egal ob auf der untersten Ebene (Blatt genannt) oder mitten im Baum (im Baum Knoten genannt) – gleich behandelt werden können. Alle Klassen implementieren dabei dieselbe Schnittstelle.

 

Wie funktioniert das Kompositum?

Schauen wir uns einmal eine Implementierung mit Hilfe des Kompositum an und nehmen dabei allerdings nicht das bereits oben erwähnte klassische Beispiel des Menübaums. Machen wir es etwas interessanter … damit hat jetzt niemand gerechnet, oder?

Das nachfolgende Beispiel ist bezüglich des Kompositum vielleicht etwas ungewöhnlich. Dies soll jedoch aufzeigen, dass auch spezielle Arten von Baumstrukturen abgebildet werden können. Alles beginnt mit der einen Schnittstelle, die später von den Knoten und Blättern implementiert wird.

In unserem Fall soll etwas berechnet und das Ergebnis vom Typ double zurückgegeben werden. Unser Blatt des Baums ist eine einfache Zahl. Nennen wir die Klasse Operand, sieht der Code dazu wie folgt aus.

Hier wird der per Konstruktor einmalig gesetzte Wert zurückgegeben. Soweit so einfach. Nun der Operator.

Hier schauen wir einmal genauer hin, auch wenn sich die Funktionsweise vermutlich fast von selbst erklärt. Ein Operator besteht aus einem Operanden, aus einer Rechenvorschrift und einem weiteren Operanden. Somit könnten wir z.B. die Rechnung 5 + 4 abbilden. Um eine größtmögliche Flexibilität bei der Rechenvorschrift zu haben nutzen wir hier das Strategie-Muster.

Hier werden zwei Operanden miteinander verknüpft. Für die Addition haben wir damit folgende Implementierung.

Für die Verknüpfung der Operanden wird der jeweilige Wert über die Methode compute() ermittelt. Vielleicht ahnt der ein oder andere von euch an dieser Stelle schon so etwas wie Rekursion und liegt damit ganz richtig. Wir verwenden für die Verknüpfung innerhalb der Rechenvorschrift nur das Interface Computable. Demnach ist es egal, ob es sich dabei um ein Operand oder ein Operator handelt. Dies genau ist die Stärke des Kompositum: alle Bestandteile des Baum werden gleich behandelt!

Ein Test der Implementierung der Addition ist an dieser Stelle schon ziemlich grün 🙂

Eine kleine Rechnung mit verschiedenen Rechenschritten lässt sich nun in dieser Form gestalten.

Wir „bauen“ die Rechnung nun als Baum auf und rufen einmalig die Methode compute() auf und erhalten das Gesamtergebnis. Wichtig dabei zu beachten ist, dass unsere Rechnung immer linksseitig ausgewertet wird! Dies liegt daran, dass in der Rechenvorschrift  zuerst firstOperand.compute() aufgerufen wird. Grafisch dargestellt sieht unser Baum aus obigem Beispiel so aus:

Composite_logo

 

Besonderheit des Beispiels

Zu unserem Beispiel ist noch zu sagen, dass hier gegenüber der üblichen Verwendung des Kompositums eine Besonderheit vorliegt. Unser Operand enthält exakt zwei Variablen vom Typ Computable. Häufig ist es jedoch so, dass ein Baumknoten eine Liste von Komponenten enthält, die bei der Verarbeitung iteriert wird. Die Grundidee bleibt jedoch dieselbe – Knoten und Blätter des Baums werden durch die Implementierung derselben Schnittstelle identisch verwendet. Demnach muss der Nutzer keine Kenntnis darüber haben, um welche Art von Komponente es sich handelt.

 

Zusammenfassung?

Wir haben uns in diesem Artikel ein Strukturmuster aus der Liste der Entwurfsmuster angeschaut, mit welchem eine Baumstruktur oder Teile-Ganzes-Beziehung abgebildet werden kann. Dies kann für Menüs, Unternehmenshierarchien oder Berechnungen genutzt werden. Mit der einmalig festgelegten Schnittstelle kann der Baum auch sehr einfach um weitere Implementierungen von Komponenten erweitert werden, welche dann nach belieben orchestriert werden können.

In welcher Situation habt ihr schon einmal einen Baum wachsen lassen?

 

Eure Spaß-Coder

Dieser Artikel basiert neben unseren Erfahrungen auf den Ausführungen aus:

Code-Beispiele auf Github:

  • https://github.com/invidit/CodeQuality.git

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.