我正在编写一个简单的游戏来学习获得更多的C ++经验,我有一个想法,我觉得多态几乎有效,但没有。在这个游戏中,Party
在Map
中相当线性地移动,但偶尔会在路上遇到Fork
。 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::*
。
您的意见?
答案 0 :(得分:6)
通过添加一个间接级别可以解决所有问题。我将使用您建议的变体,并通过允许getNext接受解析方向选择的对象来将Party与Party分离。这是一个例子(未经测试):
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';
}
};
答案 1 :(得分:1)
只要有意义并简化设计,就应该使用多态。你不应该只是因为它存在并且有一个奇特的名字而使用它。如果它确实使你的设计更简单,那么它值得耦合。
正确性和简洁性应该是每个设计决策的最终目标。
答案 2 :(得分:1)
我认为您自己发现了这些问题,可能会根据您对系统其余部分的了解或其他一些细节来解决这些问题。
如前所述:
答案 3 :(得分:0)
多态性不会带来更大的耦合,我认为它们是不同的问题。
事实上,如果您正在编程接口并遵循控制模式的一般反转,那么您将导致更少或零耦合。
在您的示例中,我没有看到位置如何与UserInterface耦合?
如果是这种情况,可以通过UserInterface和Location之间的另一个抽象级别删除耦合,例如LocationViewAdapter吗?