Was ist ein gutes Muster zum Speichern von Implementierungen einer Schnittstelle und zum Abrufen bestimmter Implementierungen?

9

Ich schreibe einen Simulator, der mehrere Schnittstellen hat, die alle simulierten Objekte implementieren. Die Schnittstelle Entity verfügt über Methoden, die alle Objekte haben müssen, wie das Abrufen von IDs und das Vorrücken des Zeitschritts für den Status des Objekts. Collidable erweitert Entity und stellt alles mit Volumen und Position dar, das bei der Ausführung von Kollisionserkennungsalgorithmen berücksichtigt werden sollte. Field erweitert Entity und stellt alles dar, das einen Standort einem Wert zuordnet; Diese werden verwendet, um Dinge wie magnetische Felder zu modellieren, die die Welt durchdringen, aber kein Volumen oder physische Form haben. RigidBody ist eine Klasse, die Collidable implementiert und Starrkörperdynamikalgorithmen bereitstellt. Ich habe eine Klasse World , die alle Entities verwaltet und Methoden hat, um die Uhr des Simulators zu beschleunigen und die Welt zu partitionieren, um die Kollisionserkennung effizienter zu machen.

Mein Problem beinhaltet das Abrufen von Entity Subtypen von World . Ursprünglich hatte World nur eine Karte von Entities nach ID, und um eine Field oder RigidBody zu erhalten, gäbe es Methoden, die die Entity aus der Karte holen und eine instanceof Prüfung machen würden plus eine Besetzung auf den gewünschten Subtyp. Ich bin mir bewusst, dass instanceof Verwendung jedoch verpönt ist, also habe ich einen anderen Ansatz versucht.

Momentan habe ich separate Karten innerhalb von World für jede Schnittstelle. Zum Beispiel gibt es eine Karte für Collidables sowie eine Karte für alle Entities . Die addCollidable() -Methode fügt beiden Maps hinzu und getCollidable() ruft nur die Collidable -Map ab. Dies vermeidet instanceof , aber es scheint mir immer noch schlechtes Design zu sein. Wenn ich mir eine andere Schnittstelle ausdenke, um Entity zu erweitern, brauche ich eine andere Karte in World und die entsprechenden Methoden.

Ich habe das Gefühl, dass dieses Thema nicht so schrecklich unklar ist. Was wird typischerweise in dieser Situation gemacht?

BEARBEITEN

Ich glaube nicht, dass das Visitor-Muster hier funktionieren wird, da Visitor es Ihnen ermöglicht, den konkreten Typ zu versenden, und einige meiner Abrufmethoden Interfacetypen abrufen müssen. Visitor würde beispielsweise funktionieren, wenn World nur Methoden zum Abrufen von RigidBodies und anderen solchen konkreten Klassen benötigt, aber ich kann keine Methode erstellen, die alle Collidables mit Visitor abruft.

    
derefed 09.04.2012, 04:29
quelle

3 Antworten

1

Hier können Sie das Besuchermuster verwenden. Dieses Tutorial zum Besuchermuster verwenden Sie für ein ähnliches Problem, das Sie haben. Ссылка

    
asela38 09.04.2012 05:08
quelle
1

Die Verwendung von instanceof ist verpönt, weil oft in Kontexten erscheint, in denen es auf unvollständige Kapselung hinweist. Zum Beispiel wird instanceof manchmal verwendet, um zwischen verschiedenen Arten von Objekten zu unterscheiden und bearbeitet sie dann abhängig von ihrem Typ. Ein sauberer Weg dies zu tun könnte sein, den Code in die entsprechenden Klassen der Objekte zu setzen und statt dessen Polymorphismus zu verwenden . Also, statt nie mit instanceof , fragen Sie sich lieber, ob Ihre aktuelle Verwendung von instanceof möglicherweise legitim ist?

Mit anderen Worten: Ist es möglich, den vom Typ der Entität abhängigen Code in die entsprechende Entitätsklasse zu verschieben? ( Natürlich, sobald Sie zu einem Ergebnis kommen, sollte dies dokumentiert werden, da sich die Dinge ändern können. )

BTW Ich denke, Sie können Ihr aktuelles Design einfach verallgemeinern , indem Sie eine Map<Class,List<Entity>> verwenden, mit der Sie Entity-Listen für eine beliebige Anzahl von Typen beibehalten können. Sie könnten auch ein Array Class[] types = {...} haben, das alle Typen enthält, die unterschieden werden müssen. Jetzt benötigen Sie nur einen einzigen Operator instanceof in einer for -Schleife innerhalb Ihrer add/removeEntity(...) -Methoden, der alle Typen, die unterschieden werden müssen, durchläuft und die Entität zu allen relevanten Listen hinzufügt / entfernt.

    
Roland Ewald 09.04.2012 20:00
quelle
0

Es erscheint mir plausibel, dass Sie ein extra Feld für die kollidierbaren Objekte in Ihrer Weltklasse verwenden, da es sich um eine spezielle Teilmenge von Daten handelt, die eine spezielle Behandlung erfordern.

Die einzige Sache, die ich ändern würde (hauptsächlich wegen des persönlichen Geschmacks), ist List<Collidable> als Typ zu verwenden, weil für Ihre Bedürfnisse - durch alle von ihnen für Kollisionsprüfungen - eine Liste ist ein schneller & amp; leichter Ansatz.

    
TheVoidSeeker 09.04.2012 14:19
quelle