一个方法应该属于谁?

6
我正在尝试使用"Proper OO"(严格的面向对象编程)设计一个简单的游戏——Pong, Arkanoid。通过过度设计,我希望能够知道下一步该做什么或不做什么...例如,谁来处理碰撞?记分员应该由谁来负责?我的第一个想法是将一些任务交给球,但这开始呈指数级扩展成为一个全能对象:球会知道它在哪里、撞到了谁,然后向记分员报告。这对球来说太多了。
5个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
5

经验法则:

  • 如果一个对象在逻辑上拥有所有涉及的状态,那么它也拥有使用该状态的方法
  • 如果一个方法需要来自多个对象的状态:
    • 如果容器对象拥有方法使用的所有对象,则容器对象也拥有该方法
    • 否则,您需要一个“桥接”对象来拥有该实用方法
    • 除非有强有力的理由使一个对象成为该方法的“控制器”(我无法举出例子)

在您的情况下,“游戏板”或“游戏环境”可能会有一个“游戏物理”类(或一组方法),它拥有碰撞检测(实用/桥接)方法。


我认为我理解其中一些,比如第一个:由于得分记录对象保留了所有得分状态,因此它还应该具有修改得分的方法。不过我不理解1.1:由于每次碰撞都发生在棋盘内,我应该使用board.collides(ball, goal1)吗? - Tordek
@[Tordek]:是的 - 实际上,您将使用board.CheckCollisions(AllObjects)来检查所有球和目标以及活动游戏范围内的任何其他可碰撞对象之间的碰撞。使用MovingObjects X CollidableObjects进行碰撞测试,并检查边界矩形进行快速测试。 - Steven A. Lowe

2
好的或坏的设计取决于它如何适应意外需求,因此我建议您准备一些可能的“游戏特色”以指导您的设计思考。由于您正在进行学习项目,所以可以尝试一些疯狂的想法。 阿卡纳oid是非常好的选择,它提供了许多选项。使不同的砖块得分不同。当被击中时,使一些砖块改变其他砖块的得分。使一些砖块需要多次击打。给球、挡板或砖块超能力。变化这些能力:其中一个使球可以通过键盘控制,另一个使它透明,另一个颠倒“重力”等等。使砖块掉落物品。 目标是,当您进行此类更改时,它会影响最少的类和方法。了解您的设计必须如何改变才能符合此标准。 使用具有重构菜单的集成开发环境(IDE),特别是“移动方法”重构。 (如果您还没有阅读过《重构》这本书,请先阅读Refactoring。)尝试将各种方法放置在不同的位置。当方法被放置在“错误”的位置时,注意哪些变得难以更改,以及当您将其放置在其他位置时哪些变得更容易。当对象负责自己的状态时,方法被放置正确;您可以“告诉”对象要做什么,而不是根据它的答案进行决策并问它关于其状态的问题。 让我们假设在您的设计中,每个精灵都是一个对象实例。 (您可以选择其他策略。)通常,运动会改变精灵的状态,因此描述特定类型精灵运动的方法可能属于该精灵的类。 碰撞检测是代码的敏感部分,因为它可能涉及检查所有可能的精灵对。您需要区分检查碰撞和通知对象发生碰撞。例如,您的球对象需要在与挡板碰撞时改变其运动方向。但一般情况下检测碰撞的算法不应该属于球类,因为其他对象对撞可能会影响游戏结果。

2

请记住,对象也可以存在于给定问题的逻辑元素中(不仅仅是像球和板这样的真实元素)。

因此,在碰撞检测中,您可以拥有一个CollidingElement类来处理位置和形状状态。然后,该对象可以通过组合嵌入到任何应在游戏中发生碰撞的对象中,并将任何需要的方法调用委托给它。


这是一个重要的声明。太多的新手似乎认为面向对象编程只是将每个可能的逻辑耦合到实际存在于现实世界中的物体上。 - Daniel Daranas

1

这真的取决于你的实现方式,但我想你可能会有一个“游戏板”对象来管理记分,或者每一边都有一个目标对象。至于碰撞,我认为你可能希望在对象之间传递事件。不过,我认为任何对象都应该知道它的位置。


0
在大多数游戏中,你会有静态元素和动态元素。动态元素会移动,它们各自独立地计算出当它们与其他元素碰撞时的情况,因为它们知道自己的形状和大小。

在这种情况下,我的演员将是球和球拍,对吗?碰撞发生时会发生什么?球和球拍应该就新方向达成一致吗?墙壁和目标是静态的吗?如果我添加移动的墙壁来挑战,那怎么办?一个物体何时不再是静态的? - Tordek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,