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

时间:2011-04-23 14:31:38

标签: c++ oop ooad

我仍然有一个小问题,抓住纯OOD的概念。

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

前两种情况真的很简单:

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);
};

现在我遇到了一个非常糟糕的问题。当然,你可以说

很好
anna.hit(bob);

直到这里我觉得它很好(如果有什么不好就请抱怨)并且读起来像散文(好的OOP代码应该)。但是你如何将击球转移到OOP?如果安娜击中鲍勃并且鲍勃跌倒,那么跌倒既不是由安娜也不是鲍勃造成的。它是由命中,失去平衡和物理造成的。

我知道这种情况只有2个选项,但不知怎的,我觉得两个都很糟糕:

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(); }
}

在这种情况下,安娜“倒下”鲍勃。但这完全没有任何意义。这并不像安娜抓住鲍勃的身体并将其移向地面。但还有另一种选择:

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(); }
}

在这种情况下,鲍勃的身体“注意到”击中使他跌倒在地,然后他“将自己”移到地上。我认为这比第一种选择更好,但这仍然感觉不对。

所以,请智能OOP人员向我解释,在现实世界中如何处理案例A修改B的状态但在OOP世界中只有B应该修改B的状态。

2 个答案:

答案 0 :(得分:10)

我认为你正陷入试图在课堂上塑造“真实”世界的陷阱而没有你设计的目的。

你的程序应该做什么?一旦你完成了这项工作,那么你就可以开始设计你想要建模的现实世界的哪些方面,以及现实世界的哪些部分无关紧要,不需要建模。将类映射到具体的真实世界对象类型只是因为它易于可视化通常是一个错误。您只需要为您的程序建立重要的概念。

OOD是关于使用抽象和多态等技术来允许对象彼此交互而不必了解彼此的实现。

在您的实施中,您需要确定要建模的行为以及每个对象想要的知识。例如,你可能希望一个人根据他被击中的难度来判断他是否想要摔倒。

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

请注意,击中我的东西不需要知道或关心它会对我产生什么影响。这是我对热门的反应。我还建模了一个“命中”对象,因为它对我的程序有意义。任何东西都可以通过创建Hit对象并让我接收它来打击我。将来我可能会被公共汽车或火车撞到我的班级而没有任何变化。

答案 1 :(得分:1)

我认为你的两难困境是因为你没有模仿时间的流逝。当你anna.hit(bob)时,一切都会发生。

如果您将实体建模为运行自己的状态机,那么事情将开始变得更像现实:

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

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

  3. 最终bob的状态更改为on_ground

  4. 然后bob的状态变为cries_for_mommy

  5. 查看State设计模式,了解如何使用OO语言实现起始图表。 “四人帮”Design Patterns一书涵盖了这一主题。