1

私は以下のような様々な種類のイベントを持っています。一般的に私はより多くの出来事を持っています。以下はマップから工場パターンを動的に読み込む方法は?

EventA 
EventB 
EventC 
EventD 
EventE 

私は、各イベントタイプを取得するコードです:イベントごと

public void run() { 
    try { 
     while (!closed.get()) { 
     ConsumerRecords records = consumer.poll(10000); 
     // Handle new records 
     for (ConsumerRecord<String, String> record : records) { 
      GenericRecord payload = decoder.decode(record.value()); 
      String eventType = String.valueOf(payload.get("eventType")); 
      String eventMapHolder = String.valueOf(payload.get("eventMapHolder")); 
      Map<String, String> eventHolder = parseStringToMap(eventHolder); 
      // here eventType will "EventA", "EventB" and so on 
      // pass eventType to get the individual factory for that event type 
      // and then pass eventHolder to a particular method of that factory class which calls appropriate Query method. 
     } 
     } 
    } catch (Exception e) { 
     // log error 
    } 
    } 

、私は別のデータベースクエリを実行する必要があるが、それらのほとんどのために少なくとも、私は1つのデータベースを実行する必要がありますそれらのすべてに共通のクエリです。たとえば:

    EventA -----> QueryA, QueryB 
        EventB -----> QueryA 
eventHolder   EventC -----> QueryA, QueryC 
        EventD -----> QueryA, QueryD 
        EventE -----> 
  • は、それでは、私はその後、私はeventHolder地図を渡します、私は私の質問を持っているコードでのeventTypeとして「EventA」を取得しましょう:以下
    EventA -----> QueryA, QueryB 
    EventB -----> QueryA 
    EventC -----> QueryA, QueryC 
    EventD -----> QueryA, QueryD 
    EventE -----> 
    

    は流れになります(それをQueryAと呼ぶ)メソッドに渡し、そのメソッド内でこのマップ上で何らかの操作を行い、新しいMapを返します。そして、この新しいMapは別のメソッドに渡されます(そのQueryBを呼びましょう)。次に、その上で何らかの操作を行い、別のMapを返します。そして、そのマップは呼び出し元に戻ります。
  • ここで、「EventB」が私の質問にあるコードのeventTypeになっているとしたら、eventHolder Mapをメソッドに渡します(これをQueryAとします)。このメソッドでは、このマップ上で何らかの操作を行います新しいマップを返します。そして、この地図は呼び出し元に返されます。
  • ここで、「EventE」が私の質問にあるコードのeventTypeになっているとしたら、eventHolder MapをEventEクラスに渡します。この場合は何もしないので、このマップを渡しますそれは発信者に戻っているので。

質問:

デザインパターン私はこの種の問題のために使うべきでしょうか?私はif/elseの使用を避けたいのですが、ここではbcozに切り替えるのが一般的です。イベントタイプがたくさんあるので、eventType値を渡して実行時に動的にロードできる個別のファクトリを作成することを考えます。

事前にすべてのイベントタイプを知っていますので、すべてのファクトリをマップに配置して初期化してから、コードを実行している間にeventTypeが来たらマップから個々のファクトリをロードできます。

これは、この問題の正しい設計パターンであれば、これを達成するためにここで抽象ファクトリパターンを使用することはできますか? "eventType"をキーとして、そのイベントタイプのインスタンスを返すファクトリに渡したいとします。だから私は"EventA"を工場に渡し、次に"EventA"のファクトリクラスを返します。そして、内部的にQueryAメソッドを呼び出すそのクラスの特定のメソッドを呼び出してから、QueryBメソッドを呼び出し、最後にMapを返します。私は上記のコードでそれを印刷します。他のイベントタイプについても同様です。

私はこのことについて何か考えていました。これが工場パターンで可能かどうか、または他のデザインパターンであるかどうかはわかりません。 (私の命名規則が台無しにされるかもしれない、私はちょうど名前を以下のものを思い付いた)

EventFactory eventFactory = EventTypeFactory.getInstance().getFactory(eventType); 
Map<String, String> holder = eventFactory.execute(eventHolder); 
+0

if-elseやswitchを使わずにこれを行う方法はわかっていましたが、覚えていません。たぶん良い睡眠の後の朝に。 – Reek

+0

返される地図の目的は何ですか? – Tony

答えて

1

さて、この質問に達成するための2つの主要なものがあります。

  • 紹介&カスタムクエリロジックを再利用します。
  • イベントタイプ文字列を関連するクエリアクションに動的にマッピングします。最初のもののために

は、私はあなたがInterpreterパターンのバリエーションを採用することを好みます。だから、このように見えるでしょう。メモリフットプリントを避けるためにシングルトンする必要があります。各子問合せクラス(QueryA exは)

public interface Query{ 
    public Map<String, String> execute(Map<String, String> map); 
} 

@Singleton 
public class QueryA implements Query{ 
    @Override 
    public Map<String, String> execute(Map<String, String> map){ 
    //queryA logic. 
    } 
}  

public class CustomQuery implements Query{ 
    List<Query> queryList; 

    public void CustomQuery(List<Query> queries){ 
    this.queryList = queries; 
    } 

    public void CustomQuery(Query query1, Query query2){ 
    this.queryList = new ArrayList(); 
    queryList.add(query1); 
    queryList.add(query2); 
    } 

    @Override 
    public Map<String, String> execute(Map<String, String> map){ 
    if(queryList == null){ 
     return map; 
    } 

    Map<String, String> eventMap = map; 
    for(Query query: queryList){ 
     eventMap = query.execute(eventMap); 
    } 
    return eventMap; 
    } 
} 

注意。上の例では、カスタムクエリアクションを使用できます。

例:QueryAB(eventAニーズ)

@Inject 
QueryA queryA; 
@Inject 
QueryB queryB; 
Query queryAB = new CustomQuery(queryA, queryB); 

は今、あなたは動的が必要QueryLogic(SあなたイベントタイプをマップMap<String, Query> eventToQueryMapを持つことができます)

例:あなたはすべて何をしたいのか、あなたのeventType文字列を受け取るたび

Map<String, Query> eventToQueryMap = new HashMap(); 
eventToQueryMap.put("EventA", queryAB); 
eventToQueryMap.put("EventB", queryA); 
//like above you can add for others too. 

が続いています。

これは、主な問題のアウトライン解決策です。独自のカスタマイズを追加することができます。 :))

0

私は私はあなたのポイントを得るかどうかわからないです。イベントを処理するオブジェクトを初期化するには、一度ファクトリパターンが必要です。ファクトリは作成パターンであり、クエリの実行とは関係ありません。だから、基本的にはあなたのアプローチは、部分的に正しいです:

Object o = EventTypeFactory.getInstance().getFactory(eventType);

これは、工場を使用することができるポイントです。私はObjectを型として使用していますので、どのパターンが "イベント処理"に最も適しているかを議論します。まず第一に、それは行動パターンでなければならない。私はコマンドパターンが便利だと言うでしょう。ただし、イベントごとに異なる可能性のあるクエリの量を表すために、Iteratorパターンが必要な場合もあります。

しかし、このようにすることは、私には少し残酷です。私は単純なテンプレートメソッドパターンもあなたが必要とするものになると思います。ただし、これはクエリ結果で何をしたいかによって異なります。ここではテンプレート方式の例である:

public abstract class EventHandler { 
    public abstract Collection<String> getQueries(); 

    public Map<String, String> handleEvent(Map<String, String> eventData) { 
     Map<String, String> result = new HashMap<>(); 

     for(String query : getQueries()) { 
     // execute the query and merge the query result into the result map 
     } 

     return result; 
    } 
} 

public class EventAEventHandler extends EventHandler { 
    public abstract Collection<String> getQueries() { 
     List<String> queries = new ArrayList<>(); 

     queries.add("YourQueryHere"); 

     return queries; 
    } 
} 

イベントを処理するには、次の

EventHandler handler = EventTypeFactory.getInstance().getFactory(eventType); 
Map<String, String> holder = handler.execute(eventMap); 

あなたが各クエリごとに地図が必要な場合は別途おList<Map<String, String>>にテンプレートメソッドの戻り値の型を変更することができ戻りました。

+0

ここで議論しよう(http://chat.stackoverflow.com/rooms/130322/factory-pattern-problem)。私はこのアプローチについて少し混乱しています。私は正確に何をしようとしているのかを説明します。 – john

0

あなたが理解している限り、工場のパターンは必要ないようです。あなたは、次のように列挙型を持つことができます。以下のような

public enum Event { 

    EventA { 
    @Override 
    Map<String, String> executeQuery() { 
     final Map<String, String> map = super.executeQuery(); 
     executeQueryB(); 
     return map; 
    } 

    private void executeQueryB() { 

    } 
    }, 
    EventB, 
    EventC, 
    EventD, 
    ; 

    Map<String, String> executeQuery() { 
    } 

} 

使用することは十分です:

return Event.valueOf("EventA").executeQuery(); 
+0

あなたは周りですか?私はこのアプローチについて少し混乱しています。私はこのチャットルームにいます(http://chat.stackoverflow.com/rooms/130321/design-pattern-problem)。ここで議論しましょう。 – john

関連する問題