游戏引擎设计选择

时间:2010-10-27 10:45:12

标签: uml

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

http://yuml.me/1252399d

而不是:

http://yuml.me/51cacb4f

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

修改:澄清符号。箭头表示继承,带有菱形的箭头表示组成,<>>。是指界面。有关符号的更多信息,请访问yUML webpage

3 个答案:

答案 0 :(得分:4)

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

首先:为什么需要表达PointLightSpotlight之间的共性?是吗

  1. 因为有些客户只想将它们用作Light,并且不关心它们的种类?
  2. 因为他们共享一些实现而您不想复制?
  3. 因为客户需要统一处理灯光

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

    • 如果您正在使用Java / C#,通常可以通过定义一个公开Lights的所有常见特征的接口(ILight)来实现。客户端只依赖于接口,而不是它的实现。每个PointLightSpotLight都会实现界面。
    • 如果您没有使用具有第一类接口的语言,请将Light声明为包含PointLightSpotLight的抽象基类。

    因为您想分享实施

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

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

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

    <强>摘要

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

    • 声明ILightSpotLight实施的接口PointLight
    • 使用实现继承或组合分享常见行为

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

    第h

答案 1 :(得分:1)

我认为你应该看一下基于组件的设计。看看this,最佳答案有一些很好的资源。

答案 2 :(得分:0)

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