多态值得增加耦合吗?

发布于 2024-07-11 15:46:45 字数 707 浏览 11 评论 0原文

我正在编写一个简单的游戏来学习更多的 C++ 经验,并且我有一个想法,我觉得多态性几乎有效,但事实并非如此。 在此游戏中,队伍地图中相当线性地移动,但偶尔会在路上遇到岔路。 叉子(基本上)是一个 std::vector。最初我打算将如下代码编写到 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()。 但在后一种情况下,位置(低级结构)必须是向用户呈现消息的位置,而不是“传递此备份”,我不认为这是优雅,因为它将 locationUserInterface::* 结合在一起。

你的意见?

I'm writing a simplistic game to learn get some more C++ experience, and I have an idea where I feel polymorphism almost works, but doesn't. In this game, the Party moves fairly linearly through a Map, but can occasionally encounter a Fork in the road. A fork is (basically) an std::vector<location*>.Originally I was going to code something like the following into the a Party member function:

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

But I was wondering if some variant of the following might be better:

CurrLocation = CurrLocation->getNext();

With Fork actually being derived from Location, and overloading some new function getNext(). But in the latter case, the location (a low level structure) would have to be the one to present the message to the user instead of "passing this back up", which I don't feel is elegant as it couples location to UserInterface::*.

Your opinions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

没有心的人 2024-07-18 15:46:45

所有问题都可以通过添加间接级别来解决。 我将使用您建议的变体,并通过允许 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';
  }
};

All problems can be solved by adding a level of indirection. I would use your suggested variant, and decouple Location from Party by allowing getNext to accept an object that resolves directional choices. Here is an example (untested):

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';
  }
};
棒棒糖 2024-07-18 15:46:45

只要多态性有意义并能简化您的设计,您就应该使用它。 你不应该仅仅因为它存在并且有一个奇特的名字就使用它。 如果它确实使您的设计更简单,那么耦合是值得的。

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

You should use polymorphism as long as it makes sense and simplifies your design. You shouldn't use it just because it exists and has a fancy name. If it does make your design simpler, then it's worth the coupling.

Correctness and simplicity should be the ultimate goal of every design decision.

柠北森屋 2024-07-18 15:46:45

我认为您自己发现了这些问题,并且可以利用您对系统其余部分的了解或这里的更多细节供我们查看来解决它。

正如已经提到的:

  1. 多态性应该被用来简化设计——在这种情况下它会做到这一点,所以很明显。
  2. 您遇到了耦合问题 - 再次被很好地发现,耦合可能会导致以后出现问题。 然而,这对我来说意味着你的方式
    应用多态性可能不是最好的方法。
  3. 接口编程应该允许您隐藏系统如何组合的内部细节,从而减少耦合。

I think you spotted the issues yourself and can probably work it out with your knowledge of the rest of the system or a few more details here for us to look at.

As has been mentioned:

  1. Polymorphism should be used to simplify the design - which it would do in this case, so well spotted.
  2. You have an issue with the coupling - again well spotted, coupling can lead to problems later on. However, what this says to me is that the way in which you are
    applying the polymorphism might not be the best way.
  3. Programming to interfaces should allow you to hide the internal details of how the system is put together and so reduce the coupling.
一直在等你来 2024-07-18 15:46:45

多态性不会带来更大的耦合,我认为它们是单独的问题。

事实上,如果您正在对接口进行编程并遵循控制模式的一般反转,那么您将导致更少或零耦合。

在您的示例中,我没有看到位置如何与用户界面耦合?

如果是这种情况,是否可以通过 UserInterface 和 Location 之间的另一个抽象级别(例如 LocationViewAdapter)来消除耦合?

Polymorphism does not lend to greater coupling, I think they are separate issues.

In fact if you are programming to interfaces and following general inversion of control patterns then you will lead to less or zero coupling.

In you example, I don't see how location is coupled to UserInterface?

If this is the case, can the coupling be removed through another level of abstraction in between UserInterface and Location, such as LocationViewAdapter?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文