我怎样才能掌握纯OOD的概念

How can I grasp the concept of pure OOD?

本文关键字:OOD 掌握      更新时间:2023-10-16

我在理解纯OOD的概念上仍然有一点问题。

假设我们有一个类Human,我们生活在一个世界里,有时人类行走(大脑命令腿),有时树木消失(人类注意到这一点),有时人类随机地相互撞击。

前两种情况真的很简单:

class Tree {
  private:
    void disappear()
    {
       // call onTreeDisappeared() for all human observers
    }
};
class Human {
  public:
    // The human notices that a tree disappeared
    void onTreeDisappeared();
  private:
    int x, y, z;
    // Human wants to walk forward
    void moveForward();
    // Hit another human, possibly causing him to fall down
    void hit(Human &target);
};

现在hit方法有了一个非常严重的问题。当然,你可以用

anna.hit(bob);

在此之前,我认为它很好(如果有不好的地方请抱怨),读起来像散文(好的OOP代码应该是这样的)。但是你如何将打击转移到OOP中呢?如果安娜打了鲍勃,鲍勃摔倒了,那么摔倒既不是安娜直接造成的,也不是鲍勃直接造成的。这是由撞击、失去平衡和物理作用造成的。

我知道这种情况下只有两个选择,但不知何故,我认为这两个都很糟糕:

public: void fallDown()
{ z = 0; }
public: void hit(Human &target)
{
  bool targetFallsDown = true; // could be random or any algorithm you like
  if(targetFallsDown)
  { target.fallDown(); }
}

在这个例子中Anna"摔倒"了Bob。但这完全说不通。又不是安娜抓住鲍勃的身体然后把它移到地上。但是还有另一个选项:

private: void fallDown()
{ z = 0; }
public: void onHitCausesMeToFallDown()
{ fallDown(); }
public: void hit(Human &target)
{
  bool targetFallsDown = true; // could be random or any algorithm you like
  if(targetFallsDown)
  { target.onHitCausesMeToFallDown(); }
}

在这种情况下,Bob的身体"注意到"撞击使他摔倒在地,然后他会"移动自己"到地上。我认为这比第一个选项好,但这仍然感觉不对。

所以,聪明的OOP同学们,请给我解释一下,当在现实世界中A修改了B的状态,而在OOP世界中只有B应该修改B的状态时,你该如何处理这种情况

我认为您正在落入一个陷阱,试图在类中模拟"真实"世界,而没有为您的设计设定一个目的。

你的程序应该做什么?一旦你解决了这个问题,你就可以开始设计你想要建模的现实世界的哪些方面,以及现实世界的哪些部分不重要,不需要建模。仅仅因为容易可视化就将类映射到具体的现实世界对象类型上,这通常是一个错误。您只需要对与您的程序相关的概念进行建模。

OOD是关于使用诸如抽象和多态性之类的技术来允许对象相互交互,而不必知道彼此的实现。

在你的实现中,你需要决定你想要建模的行为和每个对象需要的知识。例如,你可能想让一个人根据他被击中的程度来计算他是否想摔倒。

void Human::receiveHit(Hit hit)
{
    if (hit.IsBigForThisWeight(this->weight))
        this->fallDown();
}

请注意,击中我的东西不需要知道或关心它会对我产生什么影响。这是我的反应。我还建模了一个"命中"对象,因为它对我的程序很有意义。通过创建一个Hit对象并让我接收它,任何东西都可以击中我。在未来,我可以被公共汽车或火车撞倒,而不改变我的类。

我认为你的困境出现是因为你没有模拟时间的流逝。当你做anna.hit(bob)时,一切都同时发生。

如果你将实体建模为运行它们自己的状态机,那么事情将开始看起来更像现实:

  1. anna.hit(bob)导致bob的状态变为falling

  2. 在接下来的几个周期中,bob一直处于falling状态。

  3. 最终bob的状态变为on_ground

  4. bob的状态变为cries_for_mommy

查看状态设计模式,了解如何在OO语言中实现开始图表。"四人帮"的设计模式书涵盖了这个主题。