PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ Strategy Pattern Frage


Baalzamon
2009-05-15, 11:31:32
Irgendwie stehe ich gerade auf dem Schlauch. ;(

Angenommen ich habe eine Creature Klasse, welche eine attack() Methode hat. Diese soll aber austauschabr sein, d.h. zB Nah und Fernkampfangriffe sollen sollen zur Laufzeit austauschbar sein.

Imho würde sich ein Strategy Pattern anbieten.

Jetzt habe ich aber das Problem, das ich innerhalb des konkreten Ausprägung auf die Elemente der übergeordneten Klasse (in diesem Falle also Creature) zugreifen muss, um zB die Blickichtung usw. zu erfahren.

Imho müsste ich doch um an die Referenz der Kreatur zu kommen, diese der attack Methode übergeben. Das geht aber nicht da ich dan ein in-include Fehler bekomme (Creature includiert Attacktype und Attacktype includiert Creature)


Class Attacktype
{
virtual void attack(Creature* c)
}

Class MeleeAttack : public Attacktype
{
virtual void attack(Creature* c)
{ Melee attack code }
}

Class RangeAttack : public Attacktype
{
virtual void attack(Creature* c)
{ Range attack code }
}

Class Creature
{
Attacktype* at;
Quaternion orientation;
}

Creature::setAttacktype(Attacktype type)
{
at = type;
}

Creature::attack()
{
at->attack(this);
}


Irgendwie scheint mir das nicht möglich. Ist das einfach nur schlechtes Design, und wenn ja, wie würde man es sonst machen?

Ich könnte mir im Notfall damit helfen, eine evtl. ewig lange Parameterliste an die Methode zu übergeben und nicht das Objekt selber. Ist aber doch irgendwie unschön?


Class Attacktype
{
virtual void attack(Quaternion orientation, [more Parameters])
}

Creature::attack()
{
at->attack(orientation);
}


Eigentlich sollte ich sowas wissen, aber im Moment habe ich da irgendwie eine Denkblockade. :redface:

Gast
2009-05-15, 12:38:19
Nur mal so ins "Blaue" gedacht: Deine "Creature" kann sich im _Zustand_ "normal" und "Angriff" befinden.
Der Zustand Angriff enthält die Subzustände "Nahangriff" und "Fernangriff".
Was spricht gegen das State Pattern?

Expandable
2009-05-15, 12:59:21
Alternativ kannst du den Zyklus durch eine forward declaration (also "class Creature;") aufheben, falls deine Header-Datei nur Pointer und Referenzen von Creature verwendet.

Tesseract
2009-05-15, 15:50:50
Angenommen ich habe eine Creature Klasse, welche eine attack() Methode hat. Diese soll aber austauschabr sein, d.h. zB Nah und Fernkampfangriffe sollen sollen zur Laufzeit austauschbar sein.

in welchem zusammenhang brauchst du das überhaupt? je nach dem sieht nämlich imho der lösungsansatz unterschiedlich aus.

wenn es bei deinen creatures welche mit melee oder range gibt könnten diese 2 creature-arten von einer allgemeinen creature erben und die virtual methode ersetzen.
wenn jede creature melee und range kann, könntest du die einfach direkt als 2 methoden implementieren.
wenn eine creature eine art state/"stance" hat, in der sie sich befindet, könntest du das mit einem enum festlegen und der entscheidet in der methode, was passiert etc.

so würde ich es auf jedenfall nicht machen. starke objektkopplung ist normalerweise ein zeichen für ein schlechtes konzept und in dem fall imho auch einfach overkill.

oder verstehe ich dein problem gerade nicht?

Baalzamon
2009-05-15, 19:57:20
@Gast
Hmmm... über State hatte ich auch schonmal nachgedacht, könnte jetzt aber so auf die Schnelle nicht mehr sagen, warum ich das wieder verworfen hatte. Vielleicht muss ich da nochmal drüber nachdenken.

@Expandable
Danke, das sieht gut. Ich komme halt eher aus der Java Ecke, da hat man dieses Problem nicht.

@Tesseract
Die Sache ist so, das eine Kreatur zu verschiedenen Zeitpunkten, verschiedene Angriffstypen haben kann. Die eine Kreaturart ist Fernkämpfer, eine Nahkämpfer und eine die, je nach Situation, eines von beidem sein kann.

Enumeration und Switch-Blöcke möchte ich aber eigentlich vermeiden (finde ich persönlich unschön), zumal ich noch nicht sagen kann, ob nicht später noch andere Angriffsarten hinzukommen, welche eine eigene Behandlung benötigen. Die Option möchte ich mir aber offenhalten, daher würde ich das jetzt direkt ins Konzept übernehmen.

In gewisser Hinsicht hast du Recht und es ist ein Overkill, aber irgendwo ist dieses Projekt auch dazu da, um genau solche Sachen auszuprobieren.

ScottManDeath
2009-05-16, 00:40:14
Enums und switch Bloecke implementiert man mit virtuellen Methoden in einer Subklasse ;) vgl. Martin Fowler/Refactoring, Seite 82

Baalzamon
2009-05-16, 12:01:15
Enums und switch Bloecke implementiert man mit virtuellen Methoden in einer Subklasse ;) vgl. Martin Fowler/Refactoring, Seite 82
Die zweite Stimme für ein State Pattern. :uponder:

Bei Gelegenheit werde ich mir das nochmal angucken. ;)

RMC
2009-05-16, 12:19:45
Eine Statemachine ist sicher auch eine Lösung, die es sich zu überlegen lohnt.

Deine Kreatur wird sich ja auch bei einem Duell mit einem Gegner in verschiedenen Zuständen bewegen, die alle ihre eigene Programmlogik mitliefern.

zB wird die Kreatur vom RangeAttack in den MeleeAttack übergehen, und bei Gegenwehr auch sicher irgendwann in den Defense-State schalten.