我有各种类型的事件,如下所示。一般来说,我有更多活动。
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);
这是您遇到的主要问题的概要解决方案。您可以自己添加自定义。 :))