多态性是否值得增加耦合度?

6
我正在编写一个简单的游戏以增加C++经验,并且我有一个想法,其中多态性几乎可以发挥作用,但并没有。在这个游戏中,Party 相对直线地穿过 Map,但偶尔会遇到路口。一个路口基本上是一个 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(一个低级结构)将不得不向用户呈现消息,而不是“将其传回去”,我认为这不够优雅,因为它将locationUserInterface :: *耦合在一起。
您有什么看法?
4个回答

6
所有问题都可以通过增加一层间接性来解决。我会使用您建议的变体,并通过允许getNext接受一个解决方向选择的对象来使Location与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
接口命名有点可惜,除此之外完美无缺。 - ewalshe
真的吗?为什么?我们在工作中使用它。如果有不使用它的好理由,请告诉我,我会编辑答案。 - SCFrench
不错!我建议在Party中添加以下内容:“virtual IDirectionChooser& getDirectionChooser() { return this; }”,并让Move()调用它,而不是直接使用this——这将使子类通过仅覆盖该方法来使用不同的(例如外部)IDirectionChooser实现。 - j_random_hacker
根据j_random_hacker的评论进行了更新。 - SCFrench

1

只要使用多态有意义并简化了您的设计,就应该使用它。不应仅仅因为它存在并具有花哨的名称而使用它。如果确实使您的设计更简单,那么它就值得耦合。

正确性和简洁性应该是每个设计决策的最终目标。


1

我想你已经发现了问题,凭借你对系统的了解或者提供更多细节,我们可以一起解决这个问题。

正如其他人所提到的:

  1. 应该使用多态来简化设计——在这种情况下,多态是非常好的选择。
  2. 耦合度的确存在问题——同样很棒,耦合会在后期导致问题。然而,这对我来说意味着你使用多态的方式可能不是最佳方式。
  3. 编程界面可以隐藏系统如何组装的内部细节,从而减少耦合。

0

我认为多态性不会导致更大的耦合,我认为它们是分开的问题。

事实上,如果你在编程时遵循接口和控制反转模式,那么你将会减少或者消除耦合。

就你所提到的例子而言,我不明白位置与用户界面之间如何有耦合?

如果是这种情况,能否通过另一个抽象层次来消除耦合,比如LocationViewAdapter?


继承可以增加耦合,而多态性往往依赖于继承。 - David Thornley
如果您正在将基类注入到方法中,则可以通过这种方式减少耦合,这是正确的。 - Xian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接