【问题标题】:Game engine design choice [closed]游戏引擎设计选择[关闭]
【发布时间】:2010-10-27 10:45:11
【问题描述】:

我听说组合比继承更可取。因此,当我设计我的简单游戏引擎时,我倾向于执行以下操作:

http://yuml.me/1252399d

代替:

http://yuml.me/51cacb4f

这是一个好方法,还是我应该重新考虑?

编辑:澄清符号。箭头表示继承,带菱形的箭头表示组合,> 表示接口。有关该符号的更多信息,请访问 yUML webpage

【问题讨论】:

  • 你能解释一下这个符号吗?箭头是否意味着定向关联或继承? <<Light>>Light 有什么区别?
  • 我已经编辑了帖子,试图澄清符号。

标签: uml


【解决方案1】:

好的,这里有几件事要介绍。

第一:为什么要表达PointLightSpotlight之间的共性?是吗

  1. 因为有些客户只是想将它们用作Light,而不关心他们获得哪种类型?
  2. 因为它们共享一些实现并且您不想重复?

因为客户需要统一对待灯光

这是接口继承,也称为子类型。组合在这里不适用——因为没有什么可组合的。您可以通过两种方式实现这一点:您的选择很大程度上取决于您的语言。

  • 如果您使用 Java/C#,这通常可以通过定义一个接口 (ILight) 来实现,该接口公开了 Lights 的所有常见特性。客户端将只依赖于接口,而不是它的实现。 PointLightSpotLight 将分别实现该接口。
  • 如果您使用的语言不是第一类接口,请将 Light 声明为抽象基类,并从其继承 PointLightSpotLight

因为你想分享实现

通常有两种方法可以实现这一点:

  • 实现继承。定义类Light 并在其中实现常见行为。将 PointLightSpotLight 声明为继承自 Light,根据需要覆盖/添加行为。
  • 组成。定义类 PointLightSpotLight 而不从公共超类继承。实现实现常见行为的第三个类(您仍可能将其称为Light)。 PointLightSpotLight 都将包含一个“Light”实例并委托给它以实现共享行为。

对于您的具体示例,实现继承和组合之间的选择相对较少。当继承层次变得更深时,会出现前者的问题。在支持多重实现继承的语言中,它也是出了名的容易出错(例如脆弱的基类问题)。另一方面,实现继承意味着更少的输入:语言自动委托给共享行为,而使用组合则需要编写委托方法。

总结

还请注意,上述内容并不相互排斥:例如,您可以:

  • 声明一个接口ILightSpotLightPointLight 都实现了
  • 使用实现继承或组合共享常见行为

从根本上说,您需要清楚自己要达到的目标。

第一次。

【讨论】:

  • 感谢您的精彩回答!我认为我的主要教导是从你的主要观点中实现一点。灯光在容器中被平等对待,我想在灯光之间共享一些实现,例如 set_position() 之类的方法。
  • 不用担心。如果您需要更多信息,请大声喊叫。
【解决方案2】:

我认为你不应该根据某种谣言做出决定。有时组合确实很好,但需要更多的代码编写和更难的支持(如果你更改了 BasicLight 接口,你应该手动更改所有依赖类)。继承解决了这个问题,以及其他一些问题。 在某些情况下,组合更可取,但它们大多出现在复杂的项目中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    相关资源
    最近更新 更多