面向对象设计问题
如果我正在编写一个游戏,其中有一个工人(从树上)砍伐木材,我应该将“cutWood”方法放在工人类或树类中的哪里?
编辑: 我在 OOD 上读到的第一个例子是关于一个圆(一个称为圆的类),其中有一个称为“计算面积”的方法。 现在,可以肯定的是,圆不会计算自己的面积。 唯一的想法是,计算面积是一个与圆相关的操作(对圆进行的操作),
因此,cutWood 方法与工人和树都相关。
If I`m programming a game in which there is a worker that cuts wood (from trees), where would I put the "cutWood" method, in the worker class, or the tree class?
EDIT:
The first example I read on OOD was about a circle (a class called circle) which has in it a method called "calculate area".
Now, sure enough a circle doesn't calculate its own area.
The only way to think of it is that calculating area is an operation that is relevant to the circle (an operation done on the circle)
So, cutWood method is relevant to both, the worker, and the tree.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我看不出工人有任何木材切割方法的凝聚力。切割是在树上完成的,因此应该是树类的一部分。据推测,切割木材也将涉及改变木材类的某些内部状态。
工人应该在他想要的任何树上调用 cut 方法,而不是树告诉工人他应该砍伐它。如果你想像 Hans 暗示的那样抽象它,你可以为 Cut 方法创建一个 ICutable 接口,并让你的树实现它。
考虑一下您熟悉的东西:
String
。当您想要剪切字符串(分割)时,您不必在每个要执行此操作的对象中定义 splitString 方法。无论哪个对象决定分割字符串,都会发生同样的事情 - 并且通常需要了解目标对象(字符串)的内部结构才能做到这一点。许多其他对象只是调用字符串的 split 方法。字符串对象具有高内聚性 - 因为它的方法有助于完成一项常见任务 - 操作字符串。我不明白砍伐木材对工人物体本身有何贡献。
I don't see any cohesion to have a wood cutting method in the worker. The cutting is done on the tree, and should therefore be part of the tree class. Presumably, cutting the wood will also involve changing some internal state of the wood class too.
A worker should call the cut method on whatever tree he wants, rather than the tree telling the worker that he should cut it. If you want to abstract this like Hans has hinted at, you could make an ICuttable interface for the Cut method, and have your tree implement it.
Consider something you're familiar with, a
String
. When you want to cut a string (split), you don't define a splitString method in every object which is going to do this. Whatever object decides to split the string, the same thing takes place - and will usually need to know the internals of the target object (the string) in order to do it. Many other objects simply call the split method of the string. The string object has high cohesion - because it's methods contribute to a common task - manipulating strings.I don't see how cutting wood contributes much to the worker object itself.
问问自己:是工人砍木头,还是树木砍木头?
Ask yourself: Do workers cut wood, or do trees cut wood?
您基本上在问题中回答了它:“砍木头的工人”。你应该把它交给工人阶级。
You basically answered it in your question: "a worker that cuts wood". You should put it to the worker class.
为工作人员创建一个
cut(Material m)
方法,以获得额外的面向对象性。
Create a
cut(Material m)
method for the worker for extra object-orientedness.
砍伐树木时是否必须对其进行修改?
当工人砍树时,你必须修改它吗?
我想您最终会得到一个
WoodCutting
服务,该服务处理可能对两者进行修改的事件,或者依次调用worker.cutWood()
和tree。 woodCut()
啊哈,这是一个什么问题;)
do you have to modify the tree as it is being cut?
do you have to modify the worker as it cuts a tree?
i would imagine you'd end up with a
WoodCutting
service which handles the event possibly modifications to both, or in turn callingworker.cutWood()
ANDtree.woodCut()
ahah what a question ;)
对我来说听起来像是策略模式的候选者。您可能需要一个带有 PerformAction 方法的 WorkerAction 抽象类。然后 WorkerAction 类的子类将实现诸如砍树、挖金子和其他工人操作等细节。因此,子类了解树的详细信息,并且可以在树上调用必要的方法来影响正在被砍伐的树。
然后,worker 类只需要对其调用performAction() 的具体WorkerAction 实例的引用。工作人员不知道树或黄金等的详细信息。这样工作人员可以执行该操作,但您不会将工作人员限制为只能执行一项操作。事实上,如果您希望您的工作人员将来执行更多操作,您不再需要修改工作人员类。
Sounds like a candidate for the Strategy pattern to me. You may need a WorkerAction abstract class with a performAction method. Then subclasses of the WorkerAction class will implement the details such as cutting a tree, digging for gold and other worker actions. So the sub class knows about the details of the tree and can call the necessary methods on the tree to affect the tree as it is being cut.
The worker class then only need a reference to an instance of a concrete WorkerAction on which it calls performAction(). The worker does not know the details of the Tree or the Gold etc. This way the worker can perform the action but you are not limiting the worker to only one action. In fact you no longer need to modify the worker class if you want your worker to do more actions in the future.
您可以在工作器类中使用
cutWood
方法,并在树类中使用cutted
方法。显然,worker.cutWood 调用tree.cutted,这可能会返回采伐的木材量。tree.cutted 会执行让树死亡所需的所有操作。
如果您将方法调用视为“从一个对象发送到另一个对象的消息”,那么说“玩家向工人发送‘砍木头’消息,工人又向树发送‘砍伐’消息”就更有意义了。 。
You could have a
cutWood
method in the worker class, and acutted
method in the tree class. Obviously,worker.cutWood
callstree.cutted
, which might return the amount of wood harvested.tree.cutted would do all the stuff that is necessary to let the tree die.
If you consider method calls as "messages sent from one object to another", it makes a lot more sense to say "the player sends a 'cut wood' message to the worker who in turn sends a 'cut' message to the tree".
对象设计就是为类分配职责。这意味着这个问题确实没有好的答案。因为这完全取决于您如何在您的设计中建模职责。 (请参阅:Larman)
因此你 需要决定哪个对象/类负责什么。这将引导您正确回答有关要放置哪种方法的问题。
因此,问问自己这样的问题:工人是否自己决定砍伐木材?如果他这样做,他可能不需要这样排序,因此他不需要方法cut(tree)。但如果用户可以命令他这样做,他将需要一个 cut(tree) 方法。另一个例子:树必须知道自己被砍了吗?好吧,如果一棵砍伐的树只是导致他从福雷斯特中移除,那么他可能不需要这样的 tree.cut() 方法。但是,如果您将在切割过程中(重新)绘制自己的责任分配给树,则可能需要 tree.cut() 方法。这棵树甚至可以被建模为具有一定的宽度,并且他可以计算出在倒塌之前需要进行多少次砍伐。
Object design is all about assigning responsibilities to your classes. That means there really is no good answer to this question. As it all depends how you model the responsibilities in your design. (see: Larman)
Thus you need to decide what object/class is responsible for what. This will lead you to correct answers on question about were to place what kind of methods.
Thus ask you’re selves questions like: does the worker decide on his own to cut wood? If he does, he probably does not need to be ordered so, thus he will not have a need for a method cut(tree). But if the user can order him to do that, he will need a cut(tree) method. An other example: does the tree have to know he is cut? Well, if a cut tree just leads to his removal from the forrest, he might not have a need for such a tree.cut() method. But if you assign to the tree the responsibility to (re)draw himself during cutting, you might have a need for a tree.cut() method. The tree could even be modeled as having a width and that he can calculate how many cuts are needed before he collapses.
由于单个工人可能会砍伐多棵树,因此听起来您更有可能将
cutWood()
放入工人类中。Since a single worker might cut more than one tree, it sounds more likely that you'd want to put
cutWood()
in the worker class.cut()
方法不是在Saw
对象上执行吗?更严重的是,我将方法调用的目标视为“主语”,将方法本身视为“动词”,将其参数(如果动词是及物)视为“直接宾语”。因此,在此示例中,它将是
worker.cut(tree)
。Doesn't the
cut()
method go on theSaw
object?More seriously, I think of the target of the method call as the "subject", the method itself as a "verb", and its parameters (if the verb is transitive) as "direct objects." So, in this example, it would be
worker.cut(tree)
.只有解释
cutWood
的作用才能真正回答这个问题。如果
cutWood
只影响Tree
的状态,那么它属于Tree
例如,在
calculateArea
的情况下,您只需要圆的半径(假设 pi 是常数)即可进行此计算 - 不需要其他任何东西。这就是它属于Circle
的原因。不要再试图过于接近地模拟现实世界,而是看看你的方法实际上需要做什么。
This question can only really be answered if you explain what
cutWood
does.If
cutWood
only affects the state of aTree
then it belongs inTree
e.g.,In the case of
calculateArea
you only need the radius of a circle (assume pi is constant) to do this calculation - nothing else. That's why it belongs inCircle
.Stop trying to model the real world too closely and look at what your method actually needs to do.
这是一个有趣的话题。有时我自己也会想到类似的场景。我认为一个好的方法是将方法放入具有最高内聚力的类中。因此 Tree 类将是首选。另一方面,如果您尝试匹配现实世界的模型,我会说 Worker 类必须能够执行某种操作,其中包括砍伐一棵树。我经常发现自己处于这种情况,并想知道该方法的正确位置在哪里。另一种方法是一个了解工人和树的类,因此可以处理砍树机制。这样两个类(树,工人)就不会知道任何事情。
This is an intresting topic. I thought about a likewise scenario myself sometimes. I think a good way to go, is to put the method into the class with the highest cohesion. Therefore the Tree class would be the first choice. On the otherhand if you try to match a real world model i would say the Worker class has to be able to perform some kind of actions which includes cutting a Tree. I often find myself in these kind of situations and wonder where is the right place to put this method. Another approach would be a class which knows about worker and tree's, and therefore handles the cutting tree meachnism. This way both classes (tree,worker) would not know anything about it.