2009-04-21 5 views
2

次の問題のための洗練されたOOPソリューションを見つけようとしています。POJOが混在したコレクションの処理(各POJOごとに異なるハンドラを使用)

ここでは、各POJOがおそらく異なるクラスであるPOJOSイベントのコレクションがあるとします。 POJOクラス(またはタイプ)ごとに異なるルールを使用して、このコレクションを処理する必要があります。

POJOを適切なハンドラで装飾することはできません。なぜなら、私たちは世代を制御せず、そのコレクションをそのまま受け取りますからです。したがって、これに対する任意のメカニズムが同じトラップに分類されます。しかしながら、アイテム3はこの可能性を扱う。いくつかの可能な解決策、いくつかの非常に醜い、いくつかのよりエレガントなしかし複雑あり

  1. 明白な解決策、および醜いは、ハンドラにPOJOを渡すためにinstanceof演算子を使用しています。
  2. 1を少し改良すると、チェーンディスパッチャーを使用して責任の連鎖を使用して、新しいタイプに新しいディスパッチャーが必要になります。ただし、各ディスパッチャには依然としてinstanceOfが必要です。
  3. 各オブジェクトがハンドラへの参照を保持するPOJOSではなく、拡張オブジェクトを作成します。これは、POJOと私たちのプロセッサーの間の結合を作ります。
  4. 特定のイベントクラスにハンドラを登録し、イベントをハンドラにディスパッチするジェネリックス(実効javaと同様にTypesafeコンテナ)を使用するディスパッチャサービスを作成します(Javaでこれを正しく行う方法がわかります)。

4は最もエレガントですが、私にはもっと良いアイデアがあるのだろうかと思っていました。

答えて

4

簡素化:

各イベントクラスのハンドラを保存するために地図を使用します。

Map<Class, Handler> classHandlers = new HashMap<Class, Handler>(); 
classHandlers.put(EventA.class, new EventAHandler()); 
classHandlers.put(EventB.class, new EventBHandler()); 

ここで、イベントのクラスを使用してイベントのハンドラを取得します。

Handler handler = classHandlers.get(event.getClass()); 
handler.handle(event); 

もちろん、これはコーディング時に考えられるすべてのイベントクラスの知識を必要とするため、外部イベントディスパッチャーより柔軟性がありません。

+0

符号化時に既存のイベントクラスをすべて知っています:-) 新しいクラスを追加するたびに、新しいハンドラを追加する必要があります。 – KarlP

+0

+1。 "これは、コーディング時にすべての可能なイベントクラスの知識が必要です":基本的な要件の一部であるようです。 – Olivier

+1

あなたがそれらのすべてを知らなくても、未処理のPOJOクラスを単にどこかに記録するデフォルトのハンドラを作成します。今あなたは欠けているものを知っています。 –

0

このシナリオでは4番のソリューションを使用しましたが、私はそれが良いと思います。私はまた、より良い解決策について他の意見を探します。

0

4は、あなたが提示するソリューションの中で最高のものです。 #1 & 2は、instanceofが浮かんでいて混乱していると痛いでしょう。

別の解決方法:各クラスにディスパッチャメソッドを付けてアノテーションを付けます。ディスパッチャコールを処理するための中央の場所は必要なく、POJO /ディスパッチャはアノテーションの外部に結合されません。 #4の

+0

作成に責任を負わないため、注釈を付けることができない可能性があります。これは、サードパーティのクラスである可能性もあります。 – willcodejavaforfood

1

ここでは、各POJOがおそらく異なるクラスであるPOJOSイベントのコレクションがあるとします。 POJOクラス(またはタイプ)ごとに異なるルールを使用して、このコレクションを処理する必要があります。

おめでとうのPOJOのクラスには、安定した(多くの場合、追加されていません新しいクラスタイプ)であれば、あなたはVisitorパターンを使用するためのモチベーションを今説明してきました!

おそらくあなたのPOJOのコレクションに別のことをしたいので、AbstractBaseVisitorを作成して、それを拡張して必要なさまざまなことを処理できます。

POJOクラスごとに1つのラッパークラスを持つ小さなPOJOを配置し、訪問者にコールバックするvisit()関数を追加する必要があります。

+0

私は何かが欠けていない限り、これは問題を解決しません。正しいラッパーを割り当てるためのメカニズムが必要ですが、これは同じ問題です。 – user44242

0

質問は、実際には言語には無関係ではありません。いくつかの言語では、クラスを簡単に飾ることができます。しかし、Javaに固執しましょう。そこにさえ、私は「それは依存している」と言います。

私たちがやりたいことは、ハンドラの自動検出のようなものです。たとえば、ハンドラに@Handler(handles = PojoA.class)アノテーションを付けて、@Handler(主にクラスファイルのロードが必要な乱雑な方法やScannotationのようなもの)でアノテーションされたすべてのクラスをスキャンします。

Springなどのコンテキストで実行している場合、さらに興味深いオプションが発生します。

Collection<Handler> handlers = applicationContext.getBeansofType(Handler.class).values(); 
for (Handler handler : handlers) { 
    Method handleMethod = handler.getClass().getMethod("handle", Object.class); 
    Class<?> type = handleMethod.getParameterTypes()[0]; 
    register(type, handler); 
} 

(確かに、上記のコードは未検証です):あなたのディスパッチャのコードでそれらを見つけるその後、

public interface Handler<T> { 
    void handle(T object); 
} 

をして:あなたは次のような特定のインターフェースを実装するすべてのBeanを取得することができます

私はここで境界から外れることを知っています。私の指摘は、ソリューションの優雅さは、使用する言語、使用する外部ツール、使用しているフレームワークによって異なります。

関連する問題