1
class Entity {
    // various fields and methods
}

class MobileEntity extends Entity {
    // various fields and methods
}

interface Consumer {
    public void consume(final Consumable c);
}

interface Consumable {
    public void onConsume(final Consumer c);
}

class Player extends MobileEntity implements Consumer {
    // Override methods, etc
    // Can consume
}

class Npc extends MobileEntity {
    // Cannot consume anything
}

class Food implements Consumable {
    public void onConsume(final Consumer c) {
        if (c instanceof Player) {
            healPlayer();
            removeFood(1);
        }
    }
}

すべてのコードを最初に書いて申し訳ありませんが、私が説明しやすく、見れば理解できると思いました。これは私が開発しているゲーム用です。私が抱えている問題は、instanceof演算子を使用せずに消耗品 (食べ物や飲み物) を処理する方法です。Food クラスに具象クラスPlayerを設定することは避けたいと思いますが(何百もの異なる種類の Food が存在する可能性があるため)、それぞれの場合にコントラクトに例外があります (これは問題を示しています)。

すべてのエンティティ実装にhealthフィールドがあるわけではありません。それらは可能性がありますが、そうであれば、特定のものを「攻撃可能」としてマークしてからテストする必要があります

void applyDamage(int damage) {
    if (attackable) {
        health -= damage;
    }
}

ハードコーディング動作 (新しいクラスを導入するための指標) により、新しい問題が発生します。

同様のスレッドで Visitor パターンを使用している可能性があると聞いたことがありますが、現在の状況では当てはまらないと思います。

4

3 に答える 3

3

Player は Consumer を実装するため、Food の onConsume メソッドは Consumer の consumer() メソッドを呼び出すだけです。この場合、消費のプレーヤーのバージョンは、正しい仕事をします。instanceof は悪いだけでなく、オブジェクトが装飾されているときに失敗します。

于 2012-08-17T02:04:23.097 に答える
2

Consumer には consumer() メソッドがあり、Player は Consumer であるため、Consumable を Consumer に渡さない理由はありません。一方、Player、Npc、Food はすべてデータ モデルであるように思われるため、すべてのモデルからビジネス ロジック (ヘルスの増加や食品の削除など) を除外する必要がある場合があります。この場合、Food が Player によって消費されたときに何をすべきかを知っている別のクラスのセットが必要になります。

于 2012-08-17T02:05:10.990 に答える
0

ロジックが逆になっている - コンシューマブルをコンシューマに渡す必要があり、コンシューマブルにはコンシューマが呼び出すことができるメソッドが必要です。または、すべてのコンシューマがコンシューマブルが呼び出すことができるすべての可能なメソッドを実装し、正しいことを行う必要があります。それは何もないかもしれません。

于 2012-08-17T02:07:18.113 に答える