Question

Je suis en train d’écrire un jeu simpliste pour apprendre à acquérir davantage d’expérience C ++, et j’ai une idée de ce que je ressens si le polymorphisme fonctionne presque, mais pas. Dans ce jeu, le Party se déplace assez linéairement à travers un Map, mais peut occasionnellement rencontrer un Fork sur la route. Un fork est (en gros) un std::vector<location*>. À l’origine, j’allais coder quelque chose comme ce qui suit dans la fonction membre getNext():

if(!CurrLocation->fork_.empty())
   // Loop through forks and show options to the player, go where s/he wants
else
  (CurrLocation++)

Mais je me demandais si une variante de ce qui suit pourrait être meilleure:

CurrLocation = CurrLocation->getNext();

La fourchette étant en fait dérivée de la position et surchargeant une nouvelle fonction location. Mais dans ce dernier cas, la UserInterface::* (structure de bas niveau) devrait être celle qui présentera le message à l'utilisateur au lieu de & "Transmettre cette sauvegarde &"; Ce que je ne sais pas. t feel est élégant car il est couplé <=> à <=>.

Vos avis?

Était-ce utile?

La solution

Tous les problèmes peuvent être résolus en ajoutant un niveau d'indirection. J'utiliserais votre variante suggérée et découplerais l'emplacement de la partie en permettant à getNext d'accepter un objet résolvant des choix directionnels. Voici un exemple (non testé):

class Location; 

class IDirectionChooser
{
public:
  virtual bool ShouldIGoThisWay(Location & way) = 0;
};

class Location
{
public:
  virtual Location * GetNext(IDirectionChooser & chooser)
  {
    return nextLocation;
  }

  virtual Describe();
private:
  Location * nextLocation;
};

class Fork : public Location
{
public:
  virtual Location * GetNext(IDirectionChooser & chooser)
  {
    for (int i = 0; i < locations.size(); i++)
      if (chooser.ShouldIGoThisWay(*locations[i]))
        return locations[i];
  }
  virtual Describe();
private:
  vector<Location *> locations;
};

class Party : public IDirectionChooser
{
public:
  void Move()
  {
    currentLocation = currentLocation->GetNext(GetDirectionChooser());
  }

  virtual IDirectionChooser & GetDirectionChooser() { return *this; }

  virtual bool ShouldIGoThisWay(Location & way)
  {
    way.Describe();
    cout << "Do you want to go that way? y/n" << endl;

    char ans;
    cin >> ans;
    return ans == 'y';
  }
};

Autres conseils

Vous devez utiliser le polymorphisme tant que cela a du sens et simplifie votre conception. Vous ne devriez pas l'utiliser simplement parce qu'il existe et qu'il a un nom original. Si cela simplifie votre conception, le couplage en vaut la peine.

La précision et la simplicité doivent être l'objectif ultime de chaque décision de conception.

Je pense que vous avez repéré les problèmes vous-même et que vous pouvez probablement résoudre le problème en vous basant sur votre connaissance du reste du système ou sur quelques détails supplémentaires que nous pourrons examiner.

Comme cela a été mentionné:

  1. Le polymorphisme devrait être utilisé pour simplifier la conception - ce qui serait le cas dans ce cas, si bien repéré.
  2. Vous avez un problème avec le couplage. Là encore, le couplage peut entraîner des problèmes ultérieurement. Cependant, cela me dit que la façon dont vous êtes appliquer le polymorphisme pourrait ne pas être la meilleure solution.
  3. La programmation aux interfaces doit vous permettre de masquer les détails internes de la mise en place du système et de réduire ainsi le couplage.

Le polymorphisme ne donne pas lieu à un meilleur couplage, je pense qu’il s’agit de problèmes distincts.

En fait, si vous programmez des interfaces et suivez l'inversion générale des modèles de contrôle, vous obtiendrez un couplage faible ou nul.

Dans votre exemple, je ne vois pas comment la localisation est couplée à UserInterface?

Si tel est le cas, le couplage peut-il être supprimé via un autre niveau d'abstraction entre UserInterface et Location, tel que LocationViewAdapter?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top