Objektorientierte Programmierung: Teil 2 - Die richtige Strategie
Die Erschaffung einer Strategie
Ein Nachteil der obigen Umsetzung ist, dass die Klasse Game von allen konkreten Strategien abhängt, weil sie diese erstellen muss. Diese Aufgabe soll nun an eine Klasse übergeben werden, deren einzige Aufgabe die Erstellung von Strategien sein soll. Hierfür bedient man sich des Fabrik-Musters (Factory-Pattern).
Von diesem Pattern gibt es drei Ausprägungen: zum einen die Fabrik-Methode, dann die Abstrakte Fabrik und die Einfache Fabrik. Für die Anwendung hier soll eine Einfache Fabrik genutzt werden.
Design
Die Umsetzung des Einfache-Fabrik-Musters ist recht simpel. Das, was vorher die Klasse Game in der Methode start erledigt, wird in eine statische Methode create der neuen Klasse StrategyFactory ausgelagert. Game nutzt dann diese neue Klasse.
Man hätte auch auf die statische Methode verzichten und in der Methode start der Klasse Game jedes Mal eine neue Instanz von StrategyFactory erstellen können. Auch hätte die Fabrik als Attribut von Game umgesetzt werden können. Es gibt keine Gründe, dies nicht auch so zu tun.
Klassenaufteilung
An den CRC-Karten für die Strategien hat sich nichts geändert, sodass diese hier nicht noch einmal dargestellt werden sollen.
Klasse:StrategyFactoryBenötigt:IStrategy,VariableStrategy,AcceptStrategy,DeclineStrategyVerantwort.:- erstellt die richtige Strategie (je nach Konsolenparameter)
Klasse:BotBenötigt:IStrategyVerantwort.:- zählt die angenommenen Punkte
Klasse:GameBenötigt:StrategyFactory,BotVerantwort.:- erstellt den Bot und setzt die von der Fabrik erzeugte Strategie; liest Benutzereingabe, fragt Bot nach Annahme oder Ablehnung
Abhängigkeiten
Die Klasse StrategyFactory ist von allen konkreten Strategien abhängig, da sie diese erzeugt. Durch diese Abstraktion ist die Abhängigkeit von Game zu den Strategien aber verschwunden.
Vor- und Nachteile
Was ist der Vorteil der Fabrik? Die Klasse Game ist nun viel unabhängiger. Egal, ob neue Strategien hinzugefügt werden oder alte sich ändern, die Klasse Game und somit die Bibliothek libgame muss nicht neu erstellt werden. Der Code ist also gut gekapselt und lässt sich so einfach erweitern und warten. Mit diesem Design hat man das Design-Prinzip »Kapsele, was sich verändert« gut umgesetzt.
Dennoch ist es eher schlecht, dass die StrategyFactory jedes Mal angepasst werden muss, wenn eine neue Strategie hinzugefügt wird. Das lässt sich also noch verbessern.
Implementierung
Je nach Sprache kann man die Einfache Fabrik auf verschiedene Arten umsetzen. Selbst in C++ kann man den Code auf viele verschiedene Weisen erstellen. In der Beispielimplementierung wurde sich für eine einfache Lösung entschieden, bei der die drei konkreten Strategien in einem assoziativen Array gespeichert werden.
Diese Lösung entspricht in etwa auch dem Endprodukt beim freiesMagazin-Programmierwettbewerb. Sie hatte den Vorteil, dass Teilnehmer die StrategyFactory nur an zwei Stellen anpassen mussten: Zum einen musste das assoziative Array erweitert werden, zum anderen musste natürlich die neue Strategie-Header-Datei inkludiert werden.
Die C++-Implementierung der obigen Klassen kann als Archiv heruntergeladen werden: oop4-beispiel.tar.gz.
Ausblick
Derzeit nutzt die Klasse Game die statischen Operationen der StrategyFactory. Im nächsten Teil lernt man ein Muster kennen, welches dieses Konzept etwas verbessert.
Autoreninformation
Dominik Wagenführ (Webseite) ist C++-Software-Entwickler und hat täglich mit Software-Design zu tun.
Dieser Artikel ist in freiesMagazin 04/2012 (ISSN 1867-7991) erschienen. Veröffentlichung mit freundlicher Genehmigung.


