2011-04-23 74 views
5

我对抓纯OOD的概念还是有点问题。如何理解纯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?如果安娜击中鲍勃而鲍勃倒下,那么坠落既不是由安娜也不是由鲍勃直接造成的。这是由命中,失衡和物理造成的。

我知道只有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(); } 
} 

在这种情况下,Bob的身体“通知”指出,命中造成他摔倒在地,他会再“动自己”在地。我认为这比第一种方案更好,但这仍然不太合适。

所以,请聪明的OOP乡亲,向我解释,你是怎么处理的情况下,当在现实世界中A修改B的状态,但在OOP世界上只有乙方应修改B.

的状态
+3

如果树木消失,周围没有人类,他们发出声音吗? – 2011-04-23 14:35:37

+0

@Emile:真正的问题是:树木如何消失? – darioo 2011-04-23 14:44:23

+0

@darioo:如果不是人类,他们是如何出现在第一位的? – Potatoswatter 2011-04-23 19:58:58

回答

10

我认为你陷入了试图在课堂中塑造“真实”世界而不以你的设计为目的的陷阱。

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

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

在您的实施中,您需要确定要建模的行为以及每个对象需要的知识。例如,你可能想要一个人根据他受到多大的打击来计算他是否想要跌倒。

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

请注意,打我的东西并不需要知道或关心它会对我有什么影响。这是我对这次袭击的反应。我也模拟了一个“命中”对象,因为它对我的程序很有意义。任何东西都可以通过创建一个Hit对象并使我获得它来打击我。将来我可以在没有任何改变的情况下乘坐公共汽车或火车。

+1

用于创建'Hit'对象的+1。对象不必引用物理对象。任何可能成为名词的东西都可以成为一个客体,无论是物质还是概念。 – Davy8 2011-04-23 14:55:06

+1

+1以下“告诉别问。” @Kiralein:阅读http://pragprog.com/articles/tell-dont-ask获取这类问题的一般答案。 – 2011-04-25 00:48:06

+0

@Daniel T .:感谢您提供更多信息,我将以nom nom - erm - 阅读它:3 – Kirab 2011-04-25 08:32:07

1

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

如果你的模型实体运行自己的状态机,那么事情将开始寻找更喜欢现实:

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

  2. 在接下来的几个周期中,鲍勃总是在他的falling状态下直线下降。

  3. 最终鲍勃的状态变化为on_ground

  4. 然后鲍勃的状态变为cries_for_mommy

查看State设计模式,了解如何在面向对象语言中实现启动图表。 “四人帮”Design Patterns一书涵盖了这个话题。