【问题标题】:Inheritance/Interface design of a game游戏的继承/界面设计
【发布时间】:2012-01-30 19:17:08
【问题描述】:

我正在设计一款游戏,但我无法完全理解继承结构。我通常很擅长,但是这个重叠太多了,我无法全部决定。

我正在寻找帆船模型 - 想想航海时代。因此,大概所有东西都扩展了 Vessel 类。

然后有几种类型的船只类型:划船(厨房、独木舟)、方形钻机、前后钻机,具有不同的行为。这些中的每一个都进一步细分为其他几种类型。我无法决定这是否应该是 Vessel 的一系列接口或扩展。另请注意,可能会有一些交叉(船既可以是划船的也可以是方形的)这让我想到了接口?

船舶也有不同的行为:商船、战士、私掠者、海盗。我真的不知道这应该是一个接口还是另一个类的扩展。但是,在这种情况下没有类型交叉。

最后,个别船只可以有几种行为。商人可能在车队中(自卫)或独立(逃跑)。战士几乎总是攻击,除非严重超过……但可以在舰队、中队或独立工作。私掠者和海盗只有在较弱的情况下才会攻击——通常是独立的,但偶尔会成对攻击。我假设这也应该是一个接口?

我最大的问题是每种类型的舰船(护卫舰、战列舰等)几乎都可以胜任这些角色,所以我无法构建一个简单可靠的继承结构。护卫舰不能扩展人机大战,因为有些是私掠船。 Sloop 不能扩展方形索具,因为有些是前后索具的。等等。

任何想法都将不胜感激,我有点不知所措。 谢谢

【问题讨论】:

  • 我脑海中浮现的两个想法是“基于组件的设计”和“策略模式”。至于每艘船可以拥有的不同行为,这对我来说绝对是一种策略模式——每艘船都在使用多种不同策略中的一种。在维基百科上查看:en.wikipedia.org/wiki/Strategy_pattern
  • 一艘船可能在运行时从商船变成海盗船,因此接口不适用于这种动态行为。
  • @amadeus:没明白你的意思。如果您是“为接口编程”,您可以准确地做到这一点。
  • @amadeus - 船只不会动态地从商人变成海盗,更重要的是,每种船只在创建时都可以是其中一种。
  • 啊,太棒了 - 谢谢 - 我现在明白了 :)

标签: java oop design-patterns architecture


【解决方案1】:

将“行为”部分作为接口。这将帮助您毫无问题地将不同的行为分配给不同的船只。 Strategy Pattern 在这里很有帮助。简而言之,它指出应该将可变属性和常量属性分开。

对于不同的动作方式,此时作曲听起来是最合适的答案。

关于“但可以在舰队、中队或独立工作。私掠者和海盗只有在较弱的情况下才会攻击 - 通常独立但偶尔成对。”部分,我想这与继承树无关。您可以根据需要将课程“分组”。

这可能会对您有所帮助:

“有几种类型的容器样式:...”指定不同的可能行为。所以“可移动”接口及其子类就是为此而生的。在“Vessel”类中,您可以有一个“Movable”类型的成员。由于“Movable”是一个接口,任何实现它的类都可以分配给这个成员。因此,任何 Vessel 的子类都可以有任何可能的行为,我们也可以在运行时更改这些行为。您也可以将其设为 ArrayList。 (不确定您是否真的想这样做)。但是,如果您需要为同一艘船提供多种不同的行为,您可以做到。

当您说“船舶也有不同的行为:...”时,感觉就像扩展 Vessel 的单独类将满足此要求。句子“但是,在这种情况下没有类型交叉。”让生活更轻松。

对于嵌套段落“最后,个别船只可以有几种行为......”,您应该为不同的可能行为再添加一个成员。它主要是一个 ArrayList,因为一艘船将有多种攻击模式。

从最后一段开始,如果你能提供更多的细节,我也许可以提供更多的想法。

【讨论】:

  • 该图是我最初想出的那种想法——但我意识到我仍然需要另一层。例如,如何创建三个容器。一艘方形索具的商人单桅帆船,另一艘船首和船尾索具以及一艘船首和船尾索具的海盗船?我需要更多的类来获得所有可能的组合。我最终会得到 FAPirateSloop extends Pirate implements ForeAndAft,SQPirateSloop extends Pirate implements SquareRigged 等等。
【解决方案2】:

您应该分离类型并使用strategy 模式。
不可变的属性应该绑定到继承树(例如,护卫舰不会变成独木舟,这些是精确的、非行为类型,从船只继承)并且所有可能更改的内容都应该存储为对不可更改的行为类型的引用。 (Man-o-war 是一种行为类型)
AI 应该单独处理,例如状态,但也必须在架构中的不同模块中。

【讨论】:

    【解决方案3】:

    好的,这里有一些想法:

    • 船只有一种或多种推进方式(桨、帆等),您可以按组成对其进行建模(例如,有一个推进方式列表)。
    • 船只使用多种策略中的一种(使用策略模式——参见http://en.wikipedia.org/wiki/Strategy_pattern——对此)
    • 依赖于附近其他船只存在的策略将需要某种方式来查询这些其他船只 - 因此您需要某种数据结构,以便您找到哪些对象靠近哪些其他对象(查看用于广泛阶段碰撞检测的数据结构)

    作为策略模式的替代方案,您可以改用基于组件的设计。在此设置中,一艘船将由一个或多个推进组件、一个战略组件等组成。然后,您可以根据需要组合各个组件来制造不同的船只。

    作为额外的奖励,如果您希望您的游戏是数据驱动的,那么基于组件的设计非常有用,因为您可以为每种不同类型的组件编写一个保存器/加载器,而不是为每种可能的船只类型.

    如果您对这种方法感兴趣,您可能想在这里查看:

    http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

    【讨论】:

      【解决方案4】:

      我认为您需要考虑对象Composition 以及它如何帮助使事情变得更容易,而不是将其视为严格的继承。

      例如:船舶具有行为。 (组成……船委派给行为来决定如何对X情况做出反应)

      海盗是一种行为(从行为接口继承)...

      【讨论】:

      • 从技术上讲,海盗是一个带着眼罩的愤怒的家伙,他说“啊!”很多,让人们走在木板上。类似海盗的行为是一种行为 :) 请注意,这并不是一个完全可笑的观点,因为人们看到一个名为 Pirate 的类不会认为它是一种行为。
      • @StuartGolodetz - 这可能是我使用“盗版”作为一个类来消除混乱的地方?
      • 小心命名的好点...我承认我只是从最初的问题中撤出而没有考虑太多,谁不喜欢海盗? (嗯......除了忍者):D
      • 海盗不是一种行为 -> 行为在我们的系统中不是一个对象。船上有很多海盗,海盗会根据海盗的类型做出一些行为。所以你有实现接口的 IPirate 和 CaptainPirate。在您的界面中,您声明了对访问者模式的反应。
      • @AlexTheo:+1 用于介绍 CaptainPirate 课程。听起来您在争论船舶的行为部分取决于其船员的组成,这听起来很有趣。不过,这里可能是一个过于复杂的模型,不确定。
      【解决方案5】:

      我想根据 Bhusan 回答的第二段提供一些建议,我在这里全文引用:

      “关于”但可以在舰队、中队或独立工作。私掠者和海盗只会在较弱的情况下进行攻击——通常是独立攻击,但偶尔会成对攻击。”部分,我想这与继承树无关。您可以根据需要创建“组”类。”

      这使我相信您可能还需要考虑 某些 组船舶的复合模式,至少是由具有相同行为的船舶组成的那些。请参阅http://en.wikipedia.org/wiki/Composite_pattern,其中写道“复合模式描述了一组对象将以与对象的单个实例相同的方式处理。”

      例如,您说“商人可能在车队中(自卫)”,但大概他们也可以单独自卫?当然,这说起来容易做起来难,我对你的建议是不要过度思考,从你想做的原型的一小部分开始

      【讨论】:

      • 复合材料适用于总是粘在一起的群体,但当船只脱离主群体时需要小心处理——例如。如果他们航行得太远,可能需要考虑离开复合材料。
      • 我不认为复合模式在静态或动态组中占有一席之地。
      【解决方案6】:

      您不应该扩展 Vessel 类。相反,一个 Vessel 对象应该包含描述它的其他对象。 (这被称为依赖注入,令人讨厌的迂腐——忘了我说过。)你有一个推进类,有方帆、前后和桨的实例。对于大型和小型船体,您可能需要每个特殊实例。你有一个行为类来处理他们的态度。有时一个简单的整数和一个类一样有效。相反,您的军备类可能只是一些枪支。 (或两个数字,一个用于磅数。)如果您希望撞击,或者让一艘装载火箭的船,或者需要区分长枪和大炮,您可能需要返回使用 a 类。

      这使您可以根据需要即时切换特征——尽管您可能不这样做。尽管如此,您仍然可以从航行转向使用扫掠,或者将大胆的船型行为转换为商人的节省货物行为,以实施失去勇气的船长。无论如何,如果你需要它就在那里。

      【讨论】:

      • 一个很好的简洁回复,谢谢 - 我几乎从其他答案的组合中收集了相同的想法,但你说得很好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多