Entwurfsmuster in PHP – Teil II
von Matthias Kannengiesser
In diesem Teil der Reihe geht es um Techniken wie die Klassenvererbung und Objektkomposition sowie die Delegation und deren Bedeutung für die objektorientierte Entwicklung. Die Klassenvererbung funktioniert vom Prinzip her sehr einfach: Hier erbt eine Unterklasse die Implementierung und den Typ ihrer Oberklasse.
Dem abgeleiteten Objekt können neue Variablen und Methoden hinzugefügt werden, somit ist eine Wiederverwendung realisiert. Diese Technik der Wiederverwendung ist auch als White-Box-Wiederverwendung bekannt, da die Struktur des Elternobjekts eingebunden wird und somit bekannt ist.
Die Objektkomposition hingegen basiert auf der Technik, Objekte bestehender Klassen in eine Struktur einzubeziehen, beispielsweise durch Aggregation. Da hier lediglich die Schnittstelle des Objekts bekannt ist, wird diese Art von Wiederverwendung auch als Black-Box-Wiederverwendung bezeichnet.
Die Klassenvererbung ist Teil der Programmiersprache und einfach zu realisieren. Die geerbten Methoden können beibehalten oder überschrieben werden, die Variablen werden ergänzt, genutzt oder ignoriert. Hier lässt sich schon erahnen, dass die Klassenvererbung zu unsauberem Programmierstil verleiten kann.
Die Vorteile der Objektkomposition liegen ganz klar in der Flexibilität. Beziehungen zwischen Objekten lassen sich, im Gegensatz zu denen zwischen Klassen, zur Laufzeit dynamisch erzeugen und verwerfen. Darüber hinaus sind die beteiligten Objekte lediglich durch die Schnittstelle bekannt und können somit gegen eine ähnliche Schnittstelle ausgetauscht werden, ohne dass auf die unterschiedlichen Implementierungen Rücksicht genommen werden muss – sofern die Spezifikation erfüllt bleibt. Für die Nutzung der Wiederverwendung durch Objektkomposition spricht auch, dass die Klassenvererbung die Klassenhierarchie verkompliziert und es dabei zu weiteren Abhängigkeiten kommt: Jede Veränderung der Implementierung oder der Struktur einer Oberklasse wirkt sich auf die abgeleitete Unterklasse aus.
Der Vergleich zwischen Klassenvererbung und Objektkomposition ist eigentlich nicht notwendig, da beide Techniken zur Anwendung kommen müssen. Schließlich muss eine Klassenhierarchie existieren, um überhaupt Objekte zur Objektkomposition ableiten zu können. Da jedoch die Erfahrung lehrt, dass selten der kompliziertere Weg der Objektkomposition gewählt wird, sollte jeder Entwickler die Möglichkeiten und Konsequenzen beider Techniken kennen. Das Wissen um den richtigen Einsatz beider Techniken bedarf einer gewissen Erfahrung, die letzten Endes den Experten ausmacht.
Tipp: Das Durcharbeiten der Entwurfsmuster ist vor allem für unerfahrene Entwickler sinnvoll, um für die Feinheiten des objektorientierten Softwareentwurfs »sensibilisiert« zu werden.
Delegation
Mithilfe der Delegation von Anfragen kann auch mittels Objektkomposition ein Verhalten simuliert werden, welches andernfalls lediglich über Vererbung realisiert werden kann.
Um dies zu erklären, verwende ich ein Beispiel, welches bereits auf ein Entwurfsmuster zurückgreift. Es handelt es sich dabei um das Zustandsmuster (State-Pattern).
In einer Software wird eine Datei mittels eines Objekts repräsentiert. Da sich der Zustand einer Datei ändern kann (offen/geschlossen), muss sich auch das Verhalten des entsprechenden Objekts ändern. Eine Möglichkeit, dies in einem objektorientierten Entwurf zu implementieren, besteht darin, eine abstrakte Klasse namens Datei einzuführen, von der eine konkrete Klasse namens OffeneDatei und eine andere namens GeschlosseneDatei abgeleitet werden. So werden die abstrakten Methoden wie beispielsweise oeffnen() oder schliessen() überschrieben und das unterschiedliche Verhalten ist realisiert.
In dieser starren Hierarchie stellt die Änderung des Dateizustandes eine Hürde dar. Ein Objekt müsste die Klasse wechseln, was nicht möglich ist. Man müsste ein Objekt der jeweils gewünschten Klasse erzeugen, die Variablen umkopieren etc. Und selbst dann bekommt man in einem komplexen Entwurf eventuell noch Probleme mit vorhandenen Referenzen und wird so zu weiteren Änderungen gezwungen.
Der Lösungsansatz des Zustandsmusters besteht darin, ein Dateiobjekt einzuführen, welches diejenigen Daten bzw. Operationen enthält, die kontextunabhängig sind. Darüber hinaus erhält dieses Objekt eine Referenz auf ein Zustandsobjekt, in welchem die zustandsabhängigen Operationen implementiert sind.
Hinweis: Die verschiedenen Zustandsklassen stammen dabei von einer abstrakten Klasse ab.
Nun ist die Existenz eines Dateiobjekts unabhängig von seinem Zustand gesichert. Lediglich bei Veränderungen des Zustands sind Veränderungen in der Objektstruktur nötig. Diese Struktur ist zur Laufzeit dynamisch und hat somit das übergeordnete Ziel des objektorientierten Entwurfs erreicht.
Dieser Abschnitt wurde dem Buch “PHP 5 – Objektorientierte Programmierung” von Matthias Kannengiesser entnommen, das im Franzis Verlag erschienen ist. Sie können es hier direkt bestellen.














