繁体   English   中英

在哪里放置与接口相关的变量,该变量不是静态的且不是最终的

[英]Where to put a interface related variable that it is not static and final

我正处于游戏开发的初期。 这是某种基于回合的游戏,例如《战锤》或《魔兽争霸》。 有些生物可以再生他们遭受的伤害,并代表这个我有一个这样的界面

public interface Regenerative {
    void regenerates();
}

所以一个再生的生物是

public class SomeMonster() extends BaseCreature implements Regeneative{
 //Code
 private int hitPoints;

 public void regenerates(){
  hitPoints = hitPoints + regenerateValue;
 }
}

我面临的问题是,并非所有生物都能再生相同数量的生命值,因此我必须将其数量(regenerateValue)放置在某个地方。 由于我无法将其放置在界面上(因为我不希望所有生物的数量都相同),所以我考虑在生物类中添加新属性

public class SomeMonster() extends BaseCreature implements Regeneative{
 //Code
 private int regenerateValue;

 public void regenerates(){
  hitPoints = hitPoints + regenerateValue;
 }
}

但是我不喜欢这种方式(为什么不再生的生物的regenerateValue应该为0?)。 我认为它给了类不必要的属性,因此设计很糟糕。 您认为此案例的最佳方法是什么?

我面临的问题是,并非所有生物都能再生相同数量的生命值,因此我必须将其数量(regenerateValue)放置在某个地方。

为什么它必须在任何地方都是一个领域 接口的某些实现可能会对每个实例使用不同的值。 其他人可能使用恒定值。

这是实现细节 ,因此不适用于该接口。 当然,您可以将其放入实现该接口的抽象超类中。

知道界面的代码几乎肯定不应该知道或关心生物再生多少的细节-例如,它们是根据魔术而不是仅仅根据生命值再生的,或者再生的水平取决于其他功能他们的状态。 来电者不在乎。

我会将其添加到abstract BaseCreature中,不必太担心它。 您的BaseCreature最终可能会具有许多有效“关闭”的属性,但替代方法是创建一个复杂的继承树。 由于Java不支持多重继承,因此这会挫败您抽象所有可能想要的组合的能力。

如果所有怪物都已重新生成,但其中一些具有0的重新生成值(与未重新生成相同),该怎么办?

因此,您不需要下面的代码:

public class SomeMonster() extends BaseCreature {
 //Code
    protected int regenerateValue; //protected, so that subclasses can override the value

    public void regenerates(){
        hitPoints = hitPoints + regenerateValue;
    }
}

regenerateValue以0开头,因此您必须重写要实际重新生成的子类中的值

编辑删除了“工具再生”

我认为您的设计可能还可以,因为您只需要在实现Regenerative接口的类中包括regenerateValue即可。 因此,无需包含regenerateValue。

否则,您可以查看更偏重于继承而非继承的更复杂的设计模式。 这样,您就可以适应在游戏过程中向怪物动态添加再生能力以及其他“能力”的可能性,而不必在每次需要更改怪物行为时都重新编译游戏。

我使用的解决方案可能有点过头了,但这可以进行很多扩展(再生,毒害,保护...)

我使用接口“ CreatureProperties”来定义一个整数值和一个id,并且可以在每个回合上对怪物执行操作。 您可以将这些属性子类化以执行给定的属性

abstract class CreatureProperties {
   protected String id = "";
   protectd int propertyValue = 0;
   public void actOn(BaseMonster);
  // plus setter and getter
}

public RegenerationProperty implements CreatureProperties {
   final public REGENERATION_ID = "Regeneration";
   int regenerationValue = 0;

   public RegenerationProperty(int value){
      id = REGENERATION_ID;
      propertyValue= value;
   }

   public void actOn(BaseMonster monster){
      monster.setHitPoint(monster.getHitPoints()+propertyValue);
   }
}

in the BaseMonster class, you manage a set of MonsterProperty, initially empty.

    class BaseMonster {
       protected List<CreatureProperties> properties = 
         new ArrayList<CreatureProperties>();
       // plus management of propeties : add remove, iterator...

       public void update(){
          // perform all properties-linked update to monster
          foreach (CreatureProperty property : properties){
             property.actOn(this);
          }
       } 
    }

在SomeMonster的子类中,只需在实例化过程中添加此怪物类型的属性集即可。

class SomeMonster extends BaseMonster {
   public SomeMonster(){
      properties.add(new RegenerationProperty(5));  // presto : monster regenerate
   }
}

在某些情况下,我会使用Id,但该属性不会在每个刻度上都被使用(例如,更新中没有任何内容),而是例如减少伤害(id =“ LightningReduction”)或修改现有属性列表(删除所有再生属性并添加相同值的PoisonProperty ...)。

您可以在接口中添加一个方法,如getRegnerationValue(),以确保所有具有该接口的生物都具有此方法来保存值或公式(如果您要使用此方法)。

您应该问自己的问题是:如果一个生物应该再生,您怎么知道? 它将实现不同的(或扩展的)基类吗? 一种实现再生的?

如果答案是您将扩展基类(扩展到BaseRegeneratingCreature之类的东西),并且所有正在再生的生物都将扩展该类,那么这就是您的答案:BaseRegeneratingCreature应该实现该接口,并具有再生所需的所有属性。

所有非再生生物都应直接扩展BaseCreature(或另一个扩展类),并且不需要再生相关属性。

然后,您的基类可以具有以下方法:

OnStartOfTurn();

它会在BaseRegeneratingCreature中调用regenerates()(然后可能调用super()),然后在BaseCreature中执行其他操作或调用其他方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM