Pregunta

Estoy escribiendo un juego simplista para aprender a obtener más experiencia en C ++, y tengo una idea de dónde siento que el polimorfismo casi funciona, pero no funciona. En este juego, el Party se mueve bastante linealmente a través de un Map, pero ocasionalmente puede encontrar un Fork en el camino. Una bifurcación es (básicamente) un std::vector<location*>. Originalmente iba a codificar algo como lo siguiente en la función de miembro getNext():

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

Pero me preguntaba si alguna variante de lo siguiente podría ser mejor:

CurrLocation = CurrLocation->getNext();

Con Fork en realidad derivado de Location, y sobrecargando alguna nueva función location. Pero en el último caso, la UserInterface::* (una estructura de bajo nivel) debería ser la que presente el mensaje al usuario en lugar de & Quot; pasar esto de nuevo a & Quot ;, lo cual no hago ' Se siente elegante, ya que combina <=> a <=>.

¿Tus opiniones?

¿Fue útil?

Solución

Todos los problemas se pueden resolver agregando un nivel de indirección. Usaría su variante sugerida y desacoplaría Location de Party permitiendo que getNext acepte un objeto que resuelva elecciones direccionales. Aquí hay un ejemplo (no probado):

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';
  }
};

Otros consejos

Debe usar el polimorfismo siempre que tenga sentido y simplifique su diseño. No deberías usarlo solo porque existe y tiene un nombre elegante. Si hace que su diseño sea más simple, entonces vale la pena el acoplamiento.

La corrección y la simplicidad deben ser el objetivo final de cada decisión de diseño.

Creo que descubrió los problemas usted mismo y probablemente pueda resolverlo con su conocimiento del resto del sistema o algunos detalles más aquí para que los veamos.

Como se ha mencionado:

  1. El polimorfismo debe usarse para simplificar el diseño, lo que haría en este caso, muy bien visto.
  2. Tiene un problema con el acoplamiento: de nuevo bien detectado, el acoplamiento puede ocasionar problemas más adelante. Sin embargo, lo que esto me dice es que la forma en que eres aplicar el polimorfismo podría no ser la mejor manera.
  3. La programación a interfaces debería permitirle ocultar los detalles internos de cómo se ensambla el sistema y así reducir el acoplamiento.

El polimorfismo no se presta a un mayor acoplamiento, creo que son cuestiones separadas.

De hecho, si está programando para interfaces y siguiendo una inversión general de patrones de control, entonces conducirá a un acoplamiento menor o cero.

En su ejemplo, no veo cómo se acopla la ubicación a UserInterface?

Si este es el caso, ¿se puede eliminar el acoplamiento a través de otro nivel de abstracción entre UserInterface y Location, como LocationViewAdapter?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top