Disons que j'ai une classe Enemy, et le constructeur ressemblerait à quelque chose comme:
public Enemy(String name, float width, float height, Vector2 position,
float speed, int maxHp, int attackDamage, int defense... etc.){}
Cela semble mauvais parce que le constructeur a tellement de paramètres, mais lorsque je crée une instance Enemy, je dois spécifier toutes ces choses. Je veux également ces attributs dans la classe Enemy, afin de pouvoir parcourir une liste d'entre eux et obtenir / définir ces paramètres. Je pensais peut-être sous-classer l'ennemi en EnemyB, EnemyA, tout en codant en dur leur maxHp et d'autres attributs spécifiques, mais je perdrais ensuite l'accès à leurs attributs codés en dur si je voulais parcourir une liste d'ennemis (composée d'EnemyA, d'EnemyB et EnemyC).
J'essaie juste d'apprendre à coder proprement. Si cela fait une différence, je travaille en Java / C ++ / C #. Tout point dans la bonne direction est apprécié.
Réponses:
La solution consiste à regrouper les paramètres en types composites. La largeur et la hauteur sont liées conceptuellement - elles spécifient les dimensions de l'ennemi et seront généralement nécessaires ensemble. Ils pourraient être remplacés par un
Dimensions
type, ou peut-être unRectangle
type qui inclut également la position. D'un autre côté, il peut être plus judicieux de regrouperposition
et de créerspeed
unMovementData
type, surtout si l'accélération entre plus tard dans l'image. De contexte , je supposemaxHp
,attackDamage
,defense
, etc appartiennent également ensemble dans unStats
genre. Ainsi, une signature révisée pourrait ressembler à ceci:Les détails précis de l'endroit où tracer les lignes dépendront du reste de votre code et des données couramment utilisées ensemble.
la source
Enemy
est juste la classe qui ciblePlayer
, mais leur classe de base commune aCombatant
besoin des statistiques de combat.Dimensions
/MovementData
comme de vieux conteneurs de données) ou des méthodes (s'il les transforme en données abstraites types / objets). Par exemple, s'il n'avait pas déjà créé unVector2
type, il aurait peut-être fini par faire des mathématiques vectorielles dansEnemy
.Vous voudrez peut-être jeter un œil au modèle Builder . À partir du lien (avec des exemples du modèle par rapport aux alternatives):
la source
L'utilisation de sous-classes pour prédéfinir certaines valeurs n'est pas souhaitable. Sous-classe uniquement lorsqu'un nouveau type d'ennemi a un comportement différent ou de nouveaux attributs.
Le modèle d'usine est généralement utilisé pour résumer la classe exacte utilisée, mais il peut également être utilisé pour fournir des modèles pour la création d'objets:
la source
Je réserverais le sous-classement aux classes qui représentent des objets que vous pourriez utiliser indépendamment, par exemple une classe de caractères où tous les personnages, pas seulement les ennemis ont un nom, une vitesse, maxHp, ou une classe pour représenter des sprites qui ont une présence à l'écran avec une largeur, hauteur, position.
Je ne vois rien de mal en soi avec un constructeur avec beaucoup de paramètres d'entrée mais si vous voulez le diviser un peu, vous pouvez avoir un constructeur qui configure la plupart des paramètres et un autre constructeur (surchargé) qui peut être utilisé pour en définir des spécifiques et en définir d'autres sur des valeurs par défaut.
Selon la langue que vous choisissez d'utiliser, certains peuvent définir des valeurs par défaut pour les paramètres d'entrée de votre constructeur comme:
la source
Un exemple de code à ajouter à la réponse de Rory Hunter (en Java):
Maintenant, vous pouvez créer de nouvelles instances d'Ennemi comme ceci:
la source