2016-09-11 19 views
3

Javaアプリケーションでは、バックエンドで通信用にGoogle Guava EventBusを使用しています。これらのイベントの一部は、通知を有効にするためにJerseyのserver-sent eventssupportを使用してクライアント側に送信されます。クライアントサイドは特定の種類のイベントにのみ関心があり、それらのイベントはJSON形式でクライアント側に送信されます。if-elseとJavaの代わりにinstanceofを使用する

現在、我々は巨大なメソッドでJSON本体の生成を処理するためにif-elseinstanceofを使用しています。 UIEventは、フィルタとして使用されるマーカーインターフェイスに過ぎません。

@Subscribe 
public void handleEvent(final UIEvent event) { 
    if (event instanceof A) { 
    A a = (A) event; 

    } else if (event instance B) { 
    B b = (B) event; 

    } ... 
} 

このコードは、ますます多くのイベントがシステムに追加されると乱雑になり始めます。いくつかの研究の後、いくつかの選択肢がありますが、十分ではありません。

1)反射。

反射を使用するということは、正確なタイプを知らなくても宣言的な方法でイベントオブジェクトからデータを取得できることを意味します。しかし、反射を使うことは型セーフではなく、ネストされたパスを扱うときには面倒かもしれません。 a.b.c

2)多型

多型がinstanceofに良い代替のように見えますが、実際にこのケースで動作します。多型を使用するとは、toJSONUIEventのようなメソッドを追加することです。しかし、これは依存関係の流れを元に戻し、UIの詳細をイベントバスに公開します。

3)ラッパークラス

私はまた、別のクラスでJSONボディビルのロジックをカプセル化するイベントのラッパークラスを使用して考えています。次に、イベントバスのhandleEventメソッドで、イベントオブジェクトの型を取得し、命名規則を使用してラッパークラスを見つけ、ラッパークラスインスタンスを構築して、toJsonメソッドを呼び出してJSON本体を取得します。

public class AWrapper { 
    public AWrapper(A a) { 

    } 

    public Object toJson() { 

    } 
} 

これは私が考えることができる最も合理的なアプローチです。

提案とアイデアが必要です。

+0

[多型(http://refactoring.com/catalog/replaceConditionalWithPolymorphism.html)ここで標準パターンです。しかし、可能であれば、イベントのフィールドをテストして、それをオンにしてください。 – markspace

+0

多型にも私の投票があります。しかし、インタフェース上で 'toJson'のようなメソッドを使用すると、jsonを使用することができなくなります。別の解決策として、ジェネリックにシリアル化するために使用するデータプロパティ(Map など)の一般的なセットを返すメソッドを追加する方法があります。 –

+0

JacksonやGsonのような現代のライブラリはPOJOをJSONに簡単にシリアル化することができるので、特別な方法は必要ありません。内部イベントとクライアントにブロードキャストする必要があるイベントを区別するカスタム注釈を作成してみませんか?次に、 'handleEvent()'でリフレクションを使用して、アノテーションが存在するかどうかを検査します。 –

答えて

0

私はあなたがいた場合、他の-かの多くは、このようなメソッドを定義する必要はありませんでしたので、Google Guava EventBusを精密に設計されていたと信じて:

一部がEventBus リスナーのための一般的なハンドラインタフェースを提案しました。これは、有用性の問題を言及するために、 ではなく、タイプ消去のJavaの使用に関する問題に繋がります。消失に

...

、単一のクラスには、異なるタイプのパラメータで複数回ジェネリックインターフェイスを実装することはできません。これは、従来のJava Eventsから大きく後退しています.actionPerformedとkeyPressedがあまり意味のある名前でなくても、少なくとも両方のメソッドを実装できます。

独自のマーカーを作成することで、回避しようとしていた問題が再現されます。

私にとって、これはグアバはそれを使用することを提案する方法である:

EventBus eventBus = new EventBus(); 
eventBus.register(new Object(){ 
    @Subscribe 
    public void handleEvent(A a) { 
     System.out.println("a"); 
    } 
}); 

eventBus.register(new Object(){ 
    @Subscribe 
    public void handleEvent(B b) { 
     System.out.println("b"); 
    } 
}); 

... 

eventBus.post(new A()); 
eventBus.post(new B()); 

イベントタイプごとに1つのハンドラメソッド。 明らかに、サブスクライバはこの例のように匿名のクラスにする必要はありません

他の例

http://tomaszdziurko.pl/2012/01/google-guava-eventbus-easy-elegant-publisher-subscriber-cases/

関連する問題