Nehmen wir an, ich habe eine Enemy-Klasse und der Konstruktor würde ungefähr so aussehen:
public Enemy(String name, float width, float height, Vector2 position,
float speed, int maxHp, int attackDamage, int defense... etc.){}
Das sieht schlecht aus, weil der Konstruktor so viele Parameter hat, aber wenn ich eine Enemy-Instanz erstelle, muss ich all diese Dinge angeben. Ich möchte diese Attribute auch in der Enemy-Klasse haben, damit ich eine Liste von ihnen durchlaufen und diese Parameter abrufen / festlegen kann. Ich dachte, ich könnte Enemy in EnemyB, EnemyA unterteilen, während ich deren maxHp und andere spezifische Attribute fest codiere, aber dann würde ich den Zugriff auf ihre fest codierten Attribute verlieren, wenn ich eine Liste von Enemy (bestehend aus EnemyA's, EnemyB's und EnemyA's) durchlaufen wollte EnemyC's).
Ich versuche nur zu lernen, wie man sauber codiert. Wenn es einen Unterschied macht, arbeite ich in Java / C ++ / C #. Jeder Punkt in die richtige Richtung wird geschätzt.
Antworten:
Die Lösung besteht darin, die Parameter in zusammengesetzte Typen zu bündeln. Breite und Höhe hängen konzeptionell zusammen - sie geben die Dimensionen des Feindes an und werden normalerweise zusammen benötigt. Sie könnten durch einen
Dimensions
Typ ersetzt werden, oder vielleicht durch einenRectangle
Typ, der auch die Position enthält. Auf der anderen Seite könnte es sinnvoller , zu einer Gruppe machenposition
undspeed
in eineMovementData
Art, vor allem , wenn die Beschleunigung später das Bild eintritt. Von Kontext Ich gehe davon ausmaxHp
,attackDamage
,defense
usw. auch in einer zusammengehörenStats
Art. Eine überarbeitete Signatur könnte also ungefähr so aussehen:Die genauen Details zum Zeichnen der Linien hängen vom Rest Ihres Codes und den gemeinsam verwendeten Daten ab.
quelle
Enemy
ist nur die Klasse, die die angreiftPlayer
, aber ihre gemeinsame BasisklasseCombatant
benötigt die Kampfstatistik.Dimensions
/MovementData
als einfache alte Datencontainer verwendet) oder um Methoden (wenn er sie in abstrakte Daten umwandelt) handeln soll Typen / Objekte). Wenn er beispielsweise noch keinenVector2
Typ erstellt hätte, wäre er möglicherweise in Vektormathematik gelandetEnemy
.Vielleicht möchten Sie sich das Builder-Muster ansehen . Aus dem Link (mit Beispielen für Muster und Alternativen):
quelle
Das Verwenden von Unterklassen zum Voreinstellen einiger Werte ist nicht wünschenswert. Nur Unterklasse, wenn ein neuer Feindtyp ein anderes Verhalten oder neue Attribute hat.
Das Factory-Muster wird normalerweise verwendet, um die genaue verwendete Klasse zu abstrahieren. Es kann jedoch auch verwendet werden, um Vorlagen für die Objekterstellung bereitzustellen:
quelle
Ich würde Unterklassen für Klassen reservieren, die Objekte darstellen, die Sie möglicherweise unabhängig verwenden möchten, z. B. Charakterklasse, in der alle Charaktere, nicht nur Feinde, Namen, Geschwindigkeit, maxHp oder eine Klasse zur Darstellung von Sprites mit einer Präsenz auf dem Bildschirm mit Breite haben. Höhe, Position.
Ich sehe an einem Konstruktor mit vielen Eingabeparametern nichts, aber wenn Sie ihn ein wenig aufteilen möchten, könnten Sie einen Konstruktor haben, der die meisten Parameter festlegt, und einen anderen (überladenen) Konstruktor, der verwendet werden kann um bestimmte und andere auf Standardwerte zu setzen.
Abhängig davon, welche Sprache Sie verwenden, können einige Standardwerte für die Eingabeparameter Ihres Konstruktors festlegen, z.
quelle
Ein Codebeispiel zur Antwort von Rory Hunter (in Java):
Jetzt können Sie neue Instanzen von Enemy wie folgt erstellen:
quelle