我有各种类型的事件,如下所示。一般来说,我有更多活动。

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
    }
  }


对于每个事件,我需要执行不同的数据库查询,但是对于大多数事件,我至少需要执行一个对所有事件都通用的数据库查询。例如:

EventA  -----> QueryA, QueryB
EventB  -----> QueryA
EventC  -----> QueryA, QueryC
EventD  -----> QueryA, QueryD
EventE  ----->


下面是流程:

                    EventA  ----->  QueryA, QueryB
                    EventB  ----->  QueryA
eventHolder         EventC  ----->  QueryA, QueryC
                    EventD  ----->  QueryA, QueryD
                    EventE  ----->



因此,假设我在问题中的代码中将“ EventA”作为eventType获得,然后将eventHolder Map传递给一个方法(我们将其称为QueryA),然后在该方法中,我将对此映射进行一些操作并返回新地图。然后,将这个新Map传递给另一个方法(让我们调用QueryB),然后再次对它进行一些操作,然后返回另一个Map,然后该Map返回给调用方。
现在,让我们说“ EventB”作为我在问题中的代码中的eventType出现,然后将eventHolder Map传递给一个方法(我们将其称为QueryA),在该方法内,我将对此映射进行一些操作并返回一个新地图。然后,此映射将传递回给调用方。
现在让我们说“ EventE”作为我在问题中的代码中的eventType,然后将eventHolder Map传递给EventE类,并且由于在这种情况下我们不需要做任何事情,因此我将按原样传递此映射回到呼叫者。


题:

对于此类问题,应使用哪种设计模式?我想避免使用if / else或一般在这里切换bcoz,因为我有很多事件类型,因此考虑为它们创建一个单独的工厂,我们可以通过传递eventType值在运行时动态加载它。

我事先了解所有eventType,因此可以通过将其放入地图中来静态初始化所有工厂,然后在运行代码时一旦eventType出现,就可以从地图中加载各个工厂。

如果这是解决此问题的正确设计模式,如何在这里使用抽象工厂模式来完成此工作?我想将"eventType"作为键传递给工厂,该工厂将返回该事件类型的实例。假设我将"EventA"传递给工厂,然后它将为"EventA"返回工厂类,然后在该类上调用一个内部调用QueryA方法的特定方法,然后调用QueryB方法,最后调用它将返回Map,我将在上面的代码中将其打印出来。对于其他事件类型也是如此。

我在此基础上进行了思考:我不确定工厂模式是否完全可能,或者其他设计模式是否可能。 (我的命名约定可能会搞砸,我只是想出了下面的名字)

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

最佳答案

好吧,在这个问题上有两个主要的事情要实现。


介绍并重复使用自定义查询逻辑。
动态将eventType字符串映射到相关的查询操作。


首先,我希望您采用Interpreter模式的变体。所以看起来像这样。

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;
  }
}


请注意,每个子查询类(例如:QueryA)都应为Singleton,以避免占用内存。使用上面的代码,我们可以进行自定义查询操作。

例如:QueryAB(eventA的需要)

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


现在,您可以有一个Map<String, Query> eventToQueryMap,它可以将EventType动态映射到必要的QueryLogic中。

例如:

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


然后,每当您收到eventType String时,您要做的就是。

Map<String, String> eventMap = eventToQueryMap.get(eventType).execute(eventHolder);


这是您遇到的主要问题的概要解决方案。您可以自己添加自定义。 :))

10-07 16:12