Полиморфизм стоит увеличения сцепления?
-
06-07-2019 - |
Вопрос
Я пишу упрощенную игру, чтобы научиться получать больше опыта в 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?