Стоит ли полиморфизм увеличивать сцепление?

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

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 и перегружает некоторую новую функцию getNext(). Но в последнем случае location (структура низкого уровня) должен был бы представлять сообщение пользователю вместо того, чтобы «передавать эту резервную копию», что я не считаю элегантным, поскольку он связывает location с UserInterface::*. .

Ваше мнение?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
692
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

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

Полиморфизм не способствует большей связанности, я думаю, что это отдельные проблемы.

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

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

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

Наследование может увеличить сцепление, а полиморфизм, как правило, зависит от наследования.

David Thornley 09.01.2009 21:58

Верно, но если вы вводите свои базовые классы в свои методы, то это способ уменьшить вашу связь.

Xian 10.01.2009 12:34

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

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

  1. Полиморфизм следует использовать для упрощения дизайна - что он и сделал бы в этом случае, так хорошо заметным.
  2. У вас проблема с муфтой - опять же, хорошо заметная, сцепление может привести к проблемам позже. Однако это говорит мне о том, что вы применение полиморфизма может быть не лучшим способом.
  3. Программирование интерфейсов должно позволить вам скрыть внутренние детали того, как устроена система, и, таким образом, уменьшить взаимосвязь.
Ответ принят как подходящий

Все проблемы можно решить, добавив уровень косвенности. Я бы использовал предложенный вами вариант и отделил 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';
  }
};

Жалко по поводу номенклатуры интерфейса. В остальном идеально.

ewalshe 09.01.2009 03:52

Действительно? Почему? Мы используем его там, где я работаю. Если есть веская причина не использовать его, дайте мне знать, и я отредактирую ответ.

SCFrench 09.01.2009 04:32

Хороший! Я бы предложил добавить в Party: "virtual IDirectionChooser & getDirectionChooser () {return * this;}" и заставить Move () вызывать this вместо прямого использования * this - это позволит подклассу использовать другой (например, внешний) IDirectionChooser реализация, переопределив только этот метод.

j_random_hacker 09.01.2009 12:43

Обновлено на основе комментариев j_random_hacker.

SCFrench 09.01.2009 21:37

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