0

でのイベントの一元的な伝播をjavaでプログラムしたゲームでは、オブザーバを使用することがよくあります。オブザーバパターン

for(Observer o : observers) { 
    o.somethingElseHappened(); 
} 

バックいくつかの時間は、私が持っていた:イベントの伝播のために我々は、それは当然のことながら動作しますが、私たちはそれぞれ、すべてのイベントが起こって、この愚かなループを書き留めする必要が

for(Observer o : observers) { 
    o.somethingHappened(); 
} 

様ループを持っています同じことは、C++にし、メンバ関数ポインタを利用することができ、より私に最善の解決策として思わ..which

dispatchEvent(&MyAbstractHandler::somethingHappened); //loop over observers for any "event" provided 

のようなものを書きます。しかし、Javaはこれに対応できないため、私は何が最善の解決策であるか疑問に思っています。

Event-Objectを使用して、いくつかのEvent-InheritantsにオーバーロードされるメソッドhandleEvent()に渡すことができるので、多態性を利用できます。しかし、これはあなたに空のクラスのトンを与える(そして、私は一般に多型のためにクラスについて批判的である)。また、Reflectionがありますが、それは典型的なユースケースのようではなく、パフォーマンスの問題もあります。

これについてあなたの考えは何ですか?方法がないのですか?

+0

PropertyChangeSupport/PropertyChangeListenerを使用したり、エミュレートする理由は何ですか? –

答えて

4

は(MMOから話す:

public class Order implements Serializable { 
... 
transient private PropertyChangeSupport propertyChangeSupport 
    = new PropertyChangeSupport(this); 
... 
    public void addTL(...) { 
    TransactionLine t = new TransactionLine(...); 
    transactions.add(t); 
    if (propertyChangeSupport != null) 
     propertyChangeSupport.firePropertyChange("transactions", false, true); 
    } 
//each instance should add this when created 
public void addPropertyChangeListener(PropertyChangeListener listener) { 
    propertyChangeSupport.addPropertyChangeListener(listener); 
} 

これは、呼び出されるメソッドであります開発者の視点)

私はスケーラビリティのために、複数のスレッドでイベント処理を処理したいと思うかもしれません。 I通常、このようなパターン持っていた:

public class Event { EventType getType(); } 
// extend Event for special cases that require additional attributes… 

public class EventDispatcher { 
     Map<Class<? extends Event>, List<Observer>> observers; 
     void send (final Event e) { 
      for (Observer o : observers.get(e.getClass())) { 
        o.receiveEvent (e); 
      } 
     } 
    } 

それとも、あなたがenumを使用することができます:あなたはより多くのオブザーバーを処理するために、成長するにつれて、あなたはイベント処理を分割する必要があるかもしれません

public enum EventType { … } ; 
    … 
    Map <EventType,List<Observer>> observers; 
    … 
     for (Observer o : observers.get(e.getEventType())) … 

をして/他のスレッドで実行させることができます。 EventDispatcher.send(Event)メソッドを使用すると、1つの場所に拡張することができます。 (あなたが遠すぎるためにこのイベントを検出することはできません)、またはイベントハンドラが他のスレッド上で非同期処理のためにキューに注入するイベントを生成するスレッドに影響します。

本来、このモデルを人間のプレーヤーに戻す(ネットワークコードは独自のスレッドで同期的に実行されていた)イベントの伝播を処理するためにこのモデルを使用し始めましたが、キューシステムがAIや物理の伝播をスピードアップするのに役立ちました。

おそらく、Observerクラスにスイッチ/ケースフィルタを設定する必要があります。一般的には、列挙するEventTypesの数がかなり少ないと仮定すると、共通の基底クラスに分類されます。

ロマンスMMOコアの以前の反復では(後方互換性のために1.1コードベースでサポートされていましたが)、さまざまなイベントを受信するためのインターフェイスを使用しました。 (ベースクラスは、一般的なイベントレシーバーにこれらをフック - 。私たちはUIイベントハンドラと区別するためにアクションを呼び出す)

public interface EventFooHandler { 
     public void handleEventFoo (int bar, int baz); 
}; 
public class SomeObject implements EventFooHandler … 

おそらく、これらのインターフェイスは、あなたがによって意味したものでした。これは、一般的に「空のクラスのトン?」独自のスタック/スレッドで動作するもののための "口語的なJava正しい方法"。例えば私はSwingがこのように "コールバック関数"を広範に使用していると信じています。もちろん

、あなたは単にあなたが匿名クラスを使用することができ、各オブザーバーのインターフェイスを実装したくない場合は...

getEventDispatcher().registerForEventFoo 
     (new EventFooHandler { 
       public void handleEventFoo (int bar, int baz) { 
         this.doGribble (bar + 2, baz); 
      }}); 

あなたはエンティティシステムに弾丸やダイビングをかむいない場合は(私は誰かがポップインしてプラグインしようとしていることを確かめてください。おそらく、不変状態の喜びと、あなたの次のプロジェクトのためにErlangに切り替えることをお勧めしている50%のオッズについて言及しています。 「統一事象」システムは「配管」を直交させることができ、事象→観測者の経路を単一の場所で変更することができ、時間の経過と共に出てくるあらゆる事象のタイプについて、オブザーバー上の雑多な方法を伝播しない。

1

Javaでは、必要なときにトリガーできるイベントリスナーがあります。たとえば、注文が変更されるたびにOrderビューを更新する必要のあるプログラムがありました。そのため、PropertyChangeListenerを設定して、特定のプロパティが変更されるたびに(つまりtransactionsList)、注文のJTableを更新するメソッドを起動するようにしました。

同時使用の問題を避けるには、これらを使用する場合は注意が必要です。ここ

は、いくつかの例のコードである:Orderクラスから

public Order makeNewOrder() { 
    currentOrder = new Order(); 
    currentOrder.addPropertyChangeListener(new java.beans.PropertyChangeListener() { 
     public void propertyChange(java.beans.PropertyChangeEvent evt) { 
      updateOrderTable(); 
     } 
    }); 
    updateOrderTable(); 
    return currentOrder; 
} 

抽出:

/** This method is fired on propertyChange */ 
public void updateOrderTable() { 
    OrderTable ot = new OrderTable(currentOrder); 
    currentOrderTable.setModel(ot.getTableModel()); 
    currentOrderTable.setColumnModel(ot.getColumnModel()); 
    savedOrdersSelector.setModel(new javax.swing.DefaultComboBoxModel(getSavedOrders())); 
    OrderSummary.setOrder(currentOrder); 
} 
関連する問題