1

我目前正在设计 Java 游戏,并且遇到了类之间循环依赖的问题。这是我当前问题的(简化)示例:

class Game
class Player
class Ability

游戏有玩家,而玩家又拥有能力(例如咒语或攻击)。能力有一个方法,如:

public void perform(Player source, Game game);

问题是能力需要了解游戏(和玩家/游戏对象)才能执行其操作。有没有办法解决这个问题?


更新:我感谢您的回复。我现在看到技能不应该真正由玩家拥有。我很难弄清楚如何将玩家和能力联系起来。例如,像口袋妖怪这样的游戏,每个生物都有可以使用的能力。或者以收藏卡牌游戏为例,其中每张卡牌都可以具有影响游戏任何部分的能力。必须有某种方法来确定哪些玩家(或任何使用能力的对象)可以使用哪些能力,即使这些能力不直接由玩家拥有。

4

4 回答 4

4

为什么同一个包中的循环类依赖关系(假设它们在同一个包中)是一个问题?IMO,当我想到循环依赖时,我倾向于考虑包级别,而不是类级别。包循环依赖更成问题,因为它使代码更难重构。同一个包中的类很可能是相关的,一些紧密耦合有时是不可避免的。

在您的特定情况下,@Woot4Moo 指出了一些可能的设计更改,但我认为同一个包中的类之间的循环依赖关系如此糟糕并不是一般的经验法则。

于 2013-09-01T18:47:45.067 回答
3

您的能力类不需要知道它在游戏中。您需要一个代表游戏规则和组成的引擎或环境类。这将使您能够将预制玩家放入无限多的游戏引擎中。例如,您可以拥有 LowGravityEngine 和 QuantumEngine。这些引擎将允许更好的设计,将模型(玩家)与控制器(引擎或游戏)分开。

如果您不希望引擎重构您的游戏以获取玩家对象而不是能力获取游戏。这没有意义。例如在大富翁中,狗不知道如何购买房产。

于 2013-09-01T18:44:55.647 回答
0

一种设计方法是实现父子依赖。

例如,在您的Player领域:

private Game parent; 

然后,比如说,在你的Player构造函数中:

public Player(Game parent) {
    this.parent = parent;
}

当然,还有一个公共方法,例如:

public final Game getParent() {
    return parent;
}

然后您可以perform仅使用Player实例作为参数进行调用,并Game在方法主体中查询实例字段。

如果您的Game类只提供静态数据(如“规则”),您也可以Class作为参数而不是Game实例传递。

然而,这是无数种解决方案中的一种。

Woot4Moo 的解决方案对我来说非常有意义。

于 2013-09-01T18:45:08.030 回答
0

如果perform函数 inAbility需要了解 的知识Player,那么您实际上是在使用策略设计模式,因为您可以根据您为perform函数设置的参数从许多能力中进行选择(在这种情况下,这些参数是Player自身和Game)。

这样想吧。APlayer拥有能力,而是使用一个能力,由 perform 函数根据 aPlayer传递给它的参数选择要使用的正确能力。您实际上是在为 a插入一个能力Player,除了您没有指定要使用的许多能力之一,而是让该perform函数为您选择正确的操作。至关重要的是,您Player并不拥有此操作本身。因此,如果我正确理解您的问题,则根本没有任何循环依赖。

于 2013-09-01T18:47:21.803 回答