Objektorientierte Programmierung: Teil 3 – Einzigartige Registrierung
Registrier Dich!
Ein Nachteil des bisherigen Designs war, dass die StrategyFactory wissen musste, welche konkreten Strategien sie erstellt. Wieso also das Konzept nicht umkehren? Es wäre besser, wenn jede Strategie sich bei der Fabrik anmeldet. Die Fabrik muss nicht wissen, was sie genau dann erstellt, sie muss nur wissen, wie sie es macht.
Design
Die Fabrik erhält neben der create-Methode auch eine register-Methode. Die konkreten Strategien können sich nun mit einem Identifier (als String) bei der Fabrik anmelden bzw. übernimmt sinnvollerweise ein externer Strategie-Nutzer diese Anmeldung.
Zur Speicherung der Verbindung »Identifier -> Strategie« wird eine Klasse StrategyMap benutzt, die das assoziative Array darstellen soll. Da dies aber in jeder Sprache anders umgesetzt wird, bleibt die Klasse undefiniert.
Hinweis: Ein Interface unter der StrategyFactory, welches die konkreten Strategien zum Registrieren benutzen könnten, lässt sich nicht oder nur schwer umsetzen, da die StrategyFactory ein Singleton ist. (Da fällt einem die Design-Entscheidung von vorher auf die Füße.)
Klassenaufteilung
Gegenüber des letztes Teils hat sich nur die CRC-Karte der StrategyFactory geändert.
Klasse:StrategyFactoryBenötigt:IStrategyVerantwort.:- lässt neue Strategien anmelden und erstellt diese auf Zuruf
Abhängigkeiten
Die Anzahl der Abhängigkeiten hat sich theoretisch verringert, da die StrategyFactory nun nicht mehr von allen konkreten Strategien abhängig ist. Dies ist natürlich nur die halbe Wahrheit, da jemand außerhalb (normalerweise die Hauptroutine) die Anmeldung der konkreten Strategien übernehmen muss und somit von diesen abhängig ist.
Vor- und Nachteile
Theoretisch ist man nun am Ziel angekommen. Jede Klasse hat nur eine Verantwortlichkeit. Die Abhängigkeiten zwischen den Paketen/Bibliotheken sind sehr gering. libgame muss nur neu erstellt werden, wenn sich in der Deklaration der StrategyFactory etwas ändert (was hoffentlich nicht mehr der Fall sein wird) und libbot muss nur neu erstellt werden, wenn sich das Interface IStrategy ändert (was hoffentlich auch nicht passiert).
Ein weiterer Vorteil der Lösung ist, dass zur Laufzeit neue Strategien hinzukommen können. Man könnte sogar überlegen, eine unregister-Methode hinzuzufügen, sodass zur Laufzeit manche Strategien wieder entfernt werden.
Implementierung
Wie oben beschrieben übernimmt am besten die Hauptroutine die Anmeldung der konkreten Strategien bei der Fabrik. In C++ ist das die main-Funktion. Dies ist auch sinnvoll, da nur das Hauptprogramm und nicht irgendeine genutzte Bibliothek weiß, welche Strategien überhaupt eingesetzt und angeboten werden sollen. Hier könnte man bei einer Erweiterung mit eigenen Strategien diese ebenfalls anmelden.
Die C++-Implementierung der obigen Klassen kann als Archiv heruntergeladen werden: oop6-beispiel.tar.gz.
Ausblick
Das Tutorial ist fast am Ende. Im abschließenden Teil soll es möglich gemacht werden, dass während der Laufzeit die Strategien eigenständig zu anderen Strategien wechseln können.
Autoreninformation
Dominik Wagenführ (Webseite) ist C++-Software-Entwickler und hat täglich mit Software-Design zu tun. Dabei muss er sich immer Gedanken machen, dass seine Software auch in Zukunft einfach wartbar und leicht erweiterbar bleibt.
Dieser Artikel ist in freiesMagazin 05/2012 (ISSN 1867-7991) erschienen. Veröffentlichung mit freundlicher Genehmigung.


