2011-01-09 5 views
0

私はシンプルなキューベースのシステムを使って複数のアクターに起こるイベントを管理するシステムを持っています。 Eventは、時間と抽象メソッドfire()を持つ単純なクラスです。 Actorは、think()act()の2つのメソッドを実装するシンプルなインターフェイスです。一方で、Javaデザインパターン:イベントシステム、特定のアクターに対する複数のアクション

public class ActorThinkEvent extends Event { 
    private Actor actor; 

    public ActorThinkEvent(Actor actor, long time) { 
     super(time); 
     this.actor = actor; 
    } 

    public void fire() { 
     Main.game.queue.add(actor.think()); 
    } 
}
public abstract class ActorActEvent extends Event { 
    protected Actor actor; 

    protected ActorActEvent(Actor actor, long time) { 
     super(time); 
     this.actor = actor; 
    } 

    public void fire() { 
     long spent = act(); 
     Main.game.queue.add(new ActorThinkEvent(actor, time + spent)); 
    } 

    public abstract long act(); 
} 

この方法で、呼び出しは、グローバルキューに追加されるだろうActorActEventを生成することになっている、固定されている「思考」:各アクターは、そのように実装されている2つの基本的なイベントを、持っています「演技」の呼び出しは、アクションを実装するカスタムActorActEventベースのクラスを使用して行われ、費やされた時間だけが返され、新しい「思考」イベントが自動的にキューに追加されます。

私はここを参照してください問題がActorActEventベースのクラスの実装は、予め記憶された引数でActorActEvent.act()からActorクラスのいくつかのメソッドに、単純な委任に降りてくる、つまりすべての私ActEventクラスは非常に似ていることである:

public class ActorMoveEvent extends ActorActEvent { 
    private Coords delta; 

    public ActorMoveEvent(Actor actor, long time, Coords delta) { 
     super(actor, time); 
     this.delta = delta; 
    } 

    public long act() { 
     return actor.moveBy(delta); 
    } 
}
public class ActorReloadEvent extends ActorActEvent { 
    public ActorReloadEvent(Actor actor, long time) { 
     super(actor, time); 
    } 

    public long act() { 
     return actor.reload(); 
    } 
}
public class ActorPickupEvent extends ActorActEvent { 
    private ItemStash wantedItems; 

    public ActorPickupEvent(Actor actor, long time, ItemStash wantedItems) { 
     super(actor, time); 
     this.wantedItems = wantedItems; 
    } 

    public long act() { 
     return actor.pickupItems(wantedItems); 
    } 
}

私は、このようなクラスが数十点あります。私が正しく理解していれば、それは古典的な実装のCommand patternです。しかし、私は、これらの委託クラスについてすべて気にしていません。特に、それらをすべて手動で書くことについては気にしません。

Methodインスタンスとあらかじめ格納されている引数を汎用ActorActEventクラスに渡しながら、JavaのリフレクションやものをMethod.invoke()のように使うと思っていましたが、かなり遅くなります。私はこれらすべてのクラスのジェネレータを書くことを考えましたが、それは私にとってかなり不器用な解決策のように見えます。

現代のスクリプト/関数型言語であれば、ブロック/クロージャーのような構造を使い、最初に準備して、時間が来たら呼び出すようにしましょう。ああ、私は効率的にJavaでそれを作る方法を知らない。

状況を改善するために何ができるのでしょうか?

答えて

1

私のアドバイスは、反射経路を下ることです。この場合、「かなり遅い」というのが早すぎるのではないかと心配しています。反射のパフォーマンスは過去10年でかなり上がりました。あなたの名前を再解析するのに費やされる時間を節約するために、Methodのオブジェクトをキャッシュすることができます(これはおそらく最大のパフォーマンスヒットです)。この手法は、柔軟で迅速に実装できます。

あなたのクローズが本当に好きな場合は、あなたのイベントの匿名の内部クラスを試すことができます。いくつかの制限があります。あなたのメソッドを宣言して、より冗長にする必要があります。内部クラスから変数にアクセスするには、変数をfinalとして宣言する必要があります。この方法では、静的型のすべてのパフォーマンスと安全性が得られますが、各イベントに対してクラスを用意する必要があります。

歴史的に、イベントは両方の世界の行動の最悪を呈し、Objectを回り、ターゲットに依存してそれらのキャストと対処方法を知りました。

関連する問題