这是一种既定的设计模式吗?

时间:2015-10-21 07:06:15

标签: java design-patterns

我正在用Java编写游戏,其中每个Entity都可以有一个附加的EntityComponents列表。例如,可以被杀死的Entities(例如Player)将具有Health组件。检查玩家的健康状况如下:

int health = ((Health) player.getComponent(Health.KEY)).getValue();

我提出了一个轻微的快捷方式,其中每个EntityComponent都包含一个静态get方法,该方法使用适当的密钥调用实体的getComponent方法。现在检查玩家的健康状况如下:

int health = Health.of(player).getValue();

这是一个既定的设计模式吗?如果是这样,这是什么?它看起来是个好主意(本质上是一个稍微缩短代码的附加方法调用)吗?是否有更好的方法来实现我想要做的事情?

修改

一些澄清,这里......

  • Health包含getValuesetValuemodValueisDead等方法。
  • Health.of(entity)只需致电entity.getComponent(KEY),其中KEYHealth类中的字段。
  • Health.ofHealth.getValue以前分别称为Health.getHealth.getHealth,但根据评论进行了更改。
  • 并非每个Entity都是可以杀戮的 - 也就是说,不是每个Entity都可以 有健康。因此,为每个getHealth添加Entity方法会 不行。
  • 包含Killable方法的getHealth界面也不是 理想的,因为这需要每个可用的Entity 复制相同的健康相关代码。
  • 因此,选择具有单独的Health组件是a 故意为了将所有共享代码提取到一个共同的 位置。
  • 从公共基类扩展,例如KillableEntity也不是一个可行的解决方案,因为Health是许多可能的组件之一,定义一个适应所有可能组合的继承结构是不切实际的(甚至可能是不可能的)。

7 个答案:

答案 0 :(得分:1)

这是一个既定的设计模式吗?不,我会把它描述为一种反模式。

int health = Health.get(player).getHealth();

在这里,你要求Health获得玩家,然后要求玩家获得健康,这可能会导致混乱。

根据我的理解,你似乎赞成合成而不是继承。鉴于此,这样的事情可能更有意义,

int health = player.getComponentIntValue(Health.KEY);

你也可以考虑让玩家实现HasHealth接口,而不是将其简化为:

int health = player.getHealth();

答案 1 :(得分:1)

这不是答案,但我认为它会有用。

考虑使用default方法直接访问Health的成员:

public interface HealthComponent extends Health {

    Health healthComponent();

    default int currentHealth() {
        this.healthComponent().currentHealth();
    }
}

现在,如果Player实施HealthHealthComponenthealthComponent方法,您可以执行以下操作:

Player player = new Player();

player.currentHealth();

它更简洁。此模式模拟Scala的traits

一些澄清:

public interface Health {

    int currentHealth();

    void adjustHealth(int amount);

    boolean isDead();
}


public final class DefaultHealth implements Health {

    private int currentHealth;

    public DefaultHealth(final int startingHealth) {

        super();

        currentHealth = startingHealth;
    }

    public int currentHealth() {

        return currentHealth;
    }

    public void adjustHealth(final int amount) {

        if (isDead()) {

            return;
        }

        currentHealth += amount;

        if (currentHealth < 0) {

            currentHealth = 0;
        }
    }

    public boolean isDead() {

        return currentHealth > 0;
    }
}

public class Player implements HealthComponent {

    private final Health health;

    public Player(final Health health) {

        super();

        this.health = health;
    }

    public Health healthComponent() {

        return health;
    }
}

免责声明:此代码是在浏览器中编写的;它可能无法编译。

答案 2 :(得分:0)

如果您在getComponent方法背后有任何特定原因,则可以直接执行不需要添加player.getComponent方法。

int health = player.getHealth(Health.KEY);

玩家是父亲的恩赐,玩家有健康成分所以getHealth方法应该是玩家对象而不是像这样的

    int health = Health.get(player).getHealth();

答案 3 :(得分:0)

对于这个问题,我似乎可以从以下解决方案中选择一个:

  1. 从Entity派生Player类并为Entity类实现getHealth()方法

  2. 使Entity成为一个需要getHealth()方法的接口,并在Player类中实现该方法,在本例中它实现了Entity接口。

答案 4 :(得分:0)

它就像:

  

获得玩家的健康,或获得玩家的健康

我个人喜欢第一种方式。使用静态方法对于具有原始参数但没有内置上下文的方法(对于例如程序范例中的函数,例如Math.abs(int x))可能更好。

在您的情况下,健康是玩家的财产

答案 5 :(得分:0)

没有3个课程会更容易吗?

public abstract class Person {

}
public class Mortal extends Person {
    //int health; 
    //setHealth(); getHealth{}; modHealth{}; 
    //mortal(int health)
}
public class Immortal extends Person {}

然后,简单地说,

Person mortalPlayer = new Mortal(100);
mortalPlayer.getHealth();

答案 6 :(得分:0)

对我来说,这似乎是过度工程。

player.getComponent(Health.KEY)).getValue();

component的含义是什么?它很可能是一些不属于玩家的人为概念。球员有健康。玩家没有组件。

最可能是最简单的解决方案
player.getHealth();

会更好。