Вопрос

Я пишу упрощенную игру, чтобы научиться получать больше опыта в C ++, и у меня есть идея, где я чувствую, что полиморфизм почти работает, но не работает. В этой игре Party довольно линейно движется через Map, но иногда может встретиться с Fork на дороге. Вилка - это (в основном) std::vector<location*>. Первоначально я собирался написать что-то вроде следующего в функцию-член getNext():

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

Но мне было интересно, может быть лучше какой-то из следующих вариантов:

CurrLocation = CurrLocation->getNext();

Поскольку Fork фактически получен из Location и перегружен какой-то новой функцией location. Но в последнем случае UserInterface::* (низкоуровневая структура) должен был бы быть тем, чтобы представить сообщение пользователю вместо & Quot; передать это обратно & Quot; я чувствую себя элегантно, так как сочетает <=> с <=>.

Ваше мнение?

Это было полезно?

Решение

Все проблемы могут быть решены путем добавления уровня косвенности. Я бы использовал предложенный вами вариант и отделил Location от Party, позволив getNext принять объект, который разрешает выбор направления. Вот пример (не проверенный):

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

Другие советы

Вы должны использовать полиморфизм, если он имеет смысл и упрощает ваш дизайн. Вы не должны использовать его только потому, что он существует и имеет причудливое имя. Если это действительно упрощает ваш дизайн, то оно того стоит.

Правильность и простота должны быть конечной целью каждого проектного решения.

Я думаю, что вы сами обнаружили проблемы и, возможно, сможете решить их, зная остальную часть системы или несколько подробностей, на которые мы можем обратить внимание.

Как уже упоминалось:

<Ол>
  • Полиморфизм следует использовать, чтобы упростить конструкцию - что он и сделал бы в этом случае, так что его хорошо заметили.
  • У вас есть проблема со связью - опять же, хорошо заметная, связка может позже привести к проблемам. Тем не менее, это говорит мне о том, что путь, которым вы применение полиморфизма может быть не лучшим способом.
  • Программирование на интерфейсах должно позволить вам скрыть внутренние детали того, как система собрана, и таким образом уменьшить связь.
  • Полиморфизм не дает большей связи, я думаю, что это отдельные вопросы.

    На самом деле, если вы программируете интерфейсы и следуете общей инверсии шаблонов управления, это приведет к меньшему или нулевому соединению.

    В вашем примере я не вижу, как расположение связано с UserInterface?

    Если это так, можно ли удалить связь через другой уровень абстракции между UserInterface и Location, например LocationViewAdapter?

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top