1

私はゲーム開発の非常に初期の段階にいます。Warhammer や Warcraft のようなターン制のゲームです。一部のクリーチャーは、被ったダメージを再生できます。これを表すために、このようなインターフェイスがあります

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 にする必要があるのはなぜですか?)。クラスに不要なプロパティを与えているため、設計が悪いと思います。この場合の最善のアプローチは何だと思いますか?

4

7 に答える 7

3

私が直面している問題は、すべてのクリーチャーが同じ量のヒット ポイントを再生するわけではないため、その量 (regenerateValue) をどこかに配置する必要があることです。

なぜどこでもフィールドでなければならないのですか?インターフェースの実装によっては、インスタンスごとに異なる値を使用する場合があります。他の人は定数値を使用するかもしれません。

これは実装の詳細であるため、インターフェイスには不適切です。もちろん、インターフェイスを実装する抽象スーパークラスに配置することもできます。

インターフェースについて知っているコードは、ほぼ確実に、クリーチャーがどれだけ再生するかの詳細を知ったり気にしたりすべきではありません。たとえば、単にヒットポイントではなく魔法の観点から再生するか、再生のレベルが他の機能に依存する可能性があります。彼らの状態の。発信者は気にする必要はありません。

于 2012-10-10T14:01:00.920 に答える
2

私はそれをabstractBaseCreature に追加し、あまり気にしません。BaseCreature は、事実上「オフ」になっている多くのプロパティで終わる可能性がありますが、別の方法は、複雑な継承ツリーを作成することです。Java は多重継承をサポートしていないため、必要なすべての組み合わせを抽象化する機能が妨げられます。

于 2012-10-10T14:03:26.317 に答える
1

Regenerativeインターフェイスを実装するクラスにregenerateValueを含めるだけでよいので、設計はおそらく問題ないと思います。したがって、regenerateValueを含める必要はありません。

それ以外の場合は、継承よりも構成を優先する、より複雑なデザインパターンを見ることができます。このようにして、モンスターの動作を変更する必要があるたびにゲームを再コンパイルする必要がなく、ゲーム中に他の「能力」とともに再生能力をモンスターに動的に追加する可能性に応えることができます。

于 2012-10-10T14:08:43.917 に答える
1

私が使用する解決策は少し過剰に設計されているかもしれませんが、これにより多くの拡張が可能になります (再生、毒、保護...)

ID とともに整数値を定義するインターフェイス「CreatureProperties」を使用し、各ターンでモンスターに対してアクションを実行できます。これらのプロパティをサブクラス化して、特定のプロパティを実行します

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")、または既存のプロパティのリストを変更する場合 (すべての renameProperty を削除し、同じ値の PoisonProperty を追加します...)。

于 2012-10-10T16:10:11.133 に答える
1

すべてのモンスターが再生するが、一部のモンスターの再生値が 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 で始まるため、実際に再生成するサブクラスで値をオーバーライドする必要があります

「implements Regeneative」を削除するように編集

于 2012-10-10T14:05:56.287 に答える
0

インターフェイスに getRegnerationValue() などのメソッドを追加して、そのインターフェイスを持つすべてのクリーチャーが、値または式を保持するこのメソッドを持っていることを確認します。

于 2012-10-10T14:00:46.823 に答える
0

あなたが自問すべき質問はこれです: クリーチャーが再生する必要がある場合、どうすればそれを知ることができますか? 別の (または拡張する) 基本クラスを実装しますか? 回生を実装するもの?

基本クラスを (BaseRegeneratingCreature のようなものに) 拡張し、再生するすべてのクリーチャーがそのクラスを拡張するという答えがあれば、これがあなたの答えです: BaseRegeneratingCreature はそのインターフェイスを実装し、再生に必要なすべてのプロパティを持っている必要があります。

すべての非再生生物は BaseCreature (または別の拡張クラス) を直接拡張する必要があり、再生関連のプロパティは必要ありません。

次に、基本クラスに次のようなメソッドを含めることができます。

OnStartOfTurn();

これは、BaseRegeneratingCreature では regenerates() を呼び出し (そしておそらく super() を呼び出します)、BaseCreature では何か他のことを行うか、他のメソッドを呼び出します。

于 2012-10-10T14:33:38.850 に答える