簡體   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