面向对象的设计问题

时间:2010-09-30 22:34:39

标签: oop

如果我正在编写一个游戏,其中有一个工人切割木材(来自树木),我会在哪里放置“cutWood”方法,在工人阶级或树类中?

编辑: 我在OOD上读到的第一个例子是关于一个圆圈(一个叫做圆圈的类),里面有一个叫做“计算区域”的方法。 现在,确定一个圆圈不会计算自己的区域。 想到它的唯一方法是计算区域是一个与圆相关的操作(在圆上完成的操作)

因此,cutWood方法与工作者和树都相关。

12 个答案:

答案 0 :(得分:8)

我认为工人没有采用木材切割方法的凝聚力。切割在树上完成,因此应该是树类的一部分。据推测,切割木材也将涉及改变木材类的一些内部状态。

工人应该在他想要的任何树上调用切割方法,而不是树告诉工人他应该切割它。如果你想像Hans所暗示的那样抽象出来,你可以为Cut方法创建一个ICuttable接口,让你的树实现它。

考虑一下你熟悉的事情,String。如果要剪切字符串(拆分),则不要在每个要执行此操作的对象中定义splitString方法。无论什么对象决定拆分字符串,都会发生同样的事情 - 并且通常需要知道目标对象(字符串)的内部结构才能完成它。许多其他对象只是调用字符串的split方法。字符串对象具有高内聚力 - 因为它的方法有助于执行一项常见任务 - 操纵字符串。

我看不到切割木材对工人对象本身的贡献如何。

答案 1 :(得分:4)

问问自己:工人是砍伐木材,还是砍伐树木?

答案 2 :(得分:4)

你基本上在你的问题中回答:“一个砍柴的工人”。你应该把它放到工人阶级。

答案 3 :(得分:3)

创建

cut(Material m)

工作者提供额外面向对象的方法。

答案 4 :(得分:2)

你必须修剪树吗?

你是否必须在裁剪树时修改工人?

我想你最终会得到一个WoodCutting服务来处理可能对这两个事件进行修改的事件,或者依次调用worker.cutWood()tree.woodCut()

什么是问题;)

答案 5 :(得分:2)

听起来像是战略模式的候选人。您可能需要一个带有performAction方法的WorkerAction抽象类。然后,WorkerAction类的子类将实现诸如剪切树,挖掘黄金和其他工作者操作等细节。因此,子类知道树的细节,并且可以在树上调用必要的方法来影响树被切割时的效果。

然后,worker类只需要对其调用performAction()的具体WorkerAction实例的引用。工作人员不知道树或金等的细节。这样工人可以执行操作,但您不限制工人只能执行一个操作。实际上,如果您希望将来的工作人员执行更多操作,则不再需要修改工作类。

答案 6 :(得分:1)

您可以在worker类中使用cutWood方法,在树类中使用cutted方法。显然,worker.cutWood会调用tree.cutted,这可能会返回收获的木材数量。 tree.cutted会做所有使树死亡所必需的东西。

如果您将方法调用视为“从一个对象发送到另一个对象的消息”,那么说“玩家向工作人员发送'cut wood'消息更有意义”,而工作人员又发送'cut'消息给树“。

答案 7 :(得分:1)

对象设计就是为您的类分配职责。这意味着这个问题确实没有好的答案。因为这完全取决于如何在 设计中建立责任。 (见:Larman

因此需要决定什么对象/类负责什么。这将引导您正确回答有关放置何种方法的问题。

因此问你自己的问题是:工人自己决定砍木头吗?如果他这样做,他可能不需要这样订购,因此他不需要方法 cut(tree)。但是如果用户可以命令他这样做,他将需要一个剪切(树)方法。另一个例子:树必须知道他被切断了吗?好吧,如果一棵砍伐的树只是导致他从福雷斯特移除,他可能不需要这样的 tree.cut()方法。但是如果你赋予树在切割过程中(重新)绘制自己的责任,你可能需要一个 tree.cut()方法。树甚至可以被建模为具有宽度,并且他可以计算在崩溃之前需要多少切割。

答案 8 :(得分:0)

由于单个工作人员可能会裁减多个树,因此您更有可能希望将cutWood()放入工人类中。

答案 9 :(得分:0)

cut()方法不在Saw对象上吗?

更严重的是,我认为方法调用的目标是“主题”,方法本身是“动词”,其参数(如果动词是可传递的)是“直接对象”。因此,在此示例中,它将是worker.cut(tree)

答案 10 :(得分:0)

如果您解释cutWood的内容,这个问题才能真正得到解答。

如果cutWood仅影响Tree的状态,则它属于Tree,例如

public void cutWood() {
    this.height = 0;
}

calculateArea的情况下,您只需要圆的半径(假设pi是常数)来进行此计算 - 没有别的。这就是它属于Circle的原因。

停止尝试过于密切地模拟现实世界,看看你的方法实际需要做什么。

答案 11 :(得分:0)

这是一个有趣的话题。我有时会想到同样的情景。我认为一个好的方法,就是把方法放到具有最高凝聚力的课堂上。因此Tree类将是第一选择。另一方面,如果你试图匹配一个真实的世界模型,我会说工人类必须能够执行某些动作,包括切割树。我经常发现自己处于这种情况,并想知道在哪里放置这种方法的正确位置。另一种方法是一个知道工人和树的类,因此处理切割树的机制。这样两个类(树,工人)都不会对它有任何了解。