2009-04-30 7 views
0

イベントジェネレータのイディオム(http://www.javaworld.com/javaworld/jw-09-1998/jw-09-techniques.html)を実装しようとしています。私は観察可能なクラスになると少し奇妙に思えるものがある。のは、私は以下のクラスがあるとしましょう:私は彼がすることをお勧めします最初に与えたリンクでJavaでイベントジェネレータのイディオムを実装する

 
interface BakeryListener 
+ orderReceived(BakeryEvent event) 
+ orderProcessing(BakeryEvent event) 
+ orderFinished(BakeryEvent event) 
+ orderDelivered(BakeryEvent event) 

LogView, OrderReadyView etc. implements BakeryListener 
Creates a GUI for each own use 

Order 
VO/DTO object, used as the source in BakeryEvent 

BakeryDAO (the observable) 
- orders : Vector 
- listeners : Vector 
+ takeOrder, cancelOrder, bake and other regular DAO methods, 
triggering an event by calling fireEvent 
+ addBakeryListener(BakeryEvent event) 
+ removeBakeryListener(BakeryEvent event) 
- fireEvent(Order source, EVENTTYPE????) 

BakeryGUI 
Creates/gets a reference to BakeryDAO. Creates and attaches LogView, OrderReadyView as listeners on BakeryDAO. 

「イベントプロパゲータ法の火[リスナーメソッド名]を名前を。」。これは冗長であることがわかります。スナップショットを作成し、各ファイアメソッドでリスナーを繰り返します。変更するのはインターフェイス上で呼び出すメソッドだけです。したがって、私は単一のfireEventメソッドを作成しました。問題は、fireEventのイベントパラメータのデータ型を、BakeryListenersで定義されているメソッドと同期して保持することです。現在、fireEventこの(抜粋)のようになります。

 
for(BakeryListener listener : copyOfListeners){ 
    if(eventType.equals("received")) listener.orderReceived(event); 
    else if(eventType.equals("processing")) listener.orderProcessing(event); 
} 

...など私は私はそれは不可能に存在しないのeventTypeでfireEventを呼び出すために作るために文字列の代わりに列挙型を使用することができると思いますが、私はまだlistener.orderReceivedなどにType.RECEIVEDをマップする必要がありますか?

fireEventメソッドは、BakeryListenersメソッドをパラメータとして使用できますか?すなわち、(擬似コード)メソッド宣言:

fireEvent(BakeryListeners.methods eventType, Order source) 

した後だけ(IF /スイッチングすることなく)直接fireEvent内部に適切なメソッドを呼び出す:

call(listener, eventType(source)) 

イベントを作成することは不可能であろうBakeryDAO.takeOrder() - > fireEvent(eventWhoDoesntExist) - >例外?

Javaでこれを行うことはできますか?私が間違ったことを理解していれば、より良い方法でしょうか?

答えて

0

これらのシステムの実装では、私はイベント(上記のBakeryEvent)が何が起こったかについての情報を持ち、イベントを受け取ったときに何をすればよいかを聴取者に決定させます。それは、単純なintefaceをにつながるような

for (Listener l : registeredListeners) { 
    l.processEvent(event); 
} 

Javaでは、あなたが「デフォルト」の方法は残念ながら呼び出すことにしたいのスキームであなたをサポートしています何の汎用的な方法ではありません。

レン

0

よりクリーンなソースコードに「イベント」の結果につき一つの方法を作成するので、読みやすいです。あまりにも多くの情報をイベントオブジェクトに入れず、代わりにイベントリスナインタフェースのメソッド定義に頼ってください。定義されたメソッドの数を減らしてソースコードを "最適化"しようとするのは本当に意味がありません。

また、このようにして、未知のイベントが呼び出される可能性があるという問題にぶつからないようにします。

(完全に異なる何か:リスナーのリストにあなたがイベントを発生さが、CopyOnWriteArrayListを使用するたびにクローンを作成していない、それはあなたのためにそれの世話をします。)

1

私はイベントの種類を列挙し、含む考えますイベントのイベントタイプは、イベントタイプごとに1つのメソッドよりもクリーンです。

最初に、すべてのベーカーリスナーがすべてのメソッドを実装する必要がなく、1つのイベントにのみ関心がある場合は空白にしないでください。 (MouseListenerを実装したことがありますか?)

2番目の列挙型のイベントを処理する必要のないすべてのリスナーにメソッドを追加しなくても、orderBilledとorderPariedが必要な場合は、後で列挙型を追加できます。その後

public class BakeryEvent { 
    public enum Type { Received, Processing,Finished,Delivered,Billed,Paied }; 

    private Type myType; 
    private Order myOrder; 

    BakeryEvent(Order order, BakeryEvent.Type bet) {//... 

    } 
    //... 
} 


public interface BakeryListener { 
    public void handleBakeryEvent(BakeryEvent be); 
} 

public class OvenScheduler implements BakeryListener { 

    public void handleBakeryEvent(BakeryEvent be){ 
    if (BakeryEvent.Type.Received.equals(be.getEventType()) { 
     scheduldeOven(be.getOrder()); 
    } 
    } 
    // hey look I don't have to implement orderBilled() and then do nothing! 

}