如何从地图动态加载工厂模式?
How to load factory pattern dynamically from the map?
我有各种类型的事件,如下所示。总的来说我的活动比较多。
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" 作为事件类型,然后我将把 eventHolder Map 传递给一个方法(我们称之为 QueryA),在那个方法中,我会做在此地图上进行一些操作并 return 一个新地图。然后这个新的 Map 将被传递给另一个方法(让我们称之为 QueryB),然后我们将再次对其进行一些操作,然后 return 另一个 Map 然后该 map 将返回给调用者。
- 现在假设 "EventB" 在我的问题代码中作为 eventType 出现,然后我会将 eventHolder Map 传递给一个方法(我们称之为 QueryA),在该方法中,我会做一些在此地图和 return 新地图上进行操作。然后这张图会传回给调用者。
- 现在假设 "EventE" 在我的问题代码中作为 eventType 出现,然后我将把 eventHolder Map 传递给 EventE class,因为我们不需要为此做任何事情情况下,那么我将把这张地图传回给调用者。
问题:
对于这种问题,我应该使用哪种设计模式?我想避免使用 if/else 或在此处切换 bcoz 一般来说,我有很多事件类型,因此考虑为它们创建一个单独的工厂,我们可以通过传递 eventType 值在运行时动态加载它。
我事先知道所有的事件类型,所以我可以通过将它放在地图中来静态初始化所有工厂,然后一旦事件类型出现,而我们是 运行 代码,我可以从地图加载各个工厂.
如果这是解决此问题的正确设计模式,我如何在此处使用抽象工厂模式来完成此任务?我想将 "eventType"
作为键传递给工厂,该工厂将 return 该事件类型的实例。所以假设我将 "EventA"
传递给工厂,然后它将 return 工厂 class 传递给 "EventA"
,然后我们将在 class 上调用一个特定的方法它在内部调用 QueryA 方法,然后我们调用 QueryB 方法,最后它将 return 映射,我将在上面的代码中将其打印出来。其他事件类型也类似。
基于这个原因,我在想一些事情:我不确定工厂模式是否完全可行,或者是否可能是其他设计模式。 (我的命名约定可能搞砸了,我只是想出了下面的名字)
EventFactory eventFactory = EventTypeFactory.getInstance().getFactory(eventType);
Map<String, String> holder = eventFactory.execute(eventHolder);
我不确定我是否明白你的意思。您只需要一次工厂模式来初始化处理您的事件的对象。工厂是一种创建模式,与查询的执行无关。所以基本上你的方法是部分正确的:
Object o = EventTypeFactory.getInstance().getFactory(eventType);
这是可以使用工厂的地方。我故意使用 Object 作为类型,因为我们现在要讨论哪种模式最适合 "event handling"。首先它必须是一种行为模式。我会说命令模式可以派上用场。但是,您可能还需要迭代器模式来表示每个事件的潜在不同查询量。
然而,这样做对我来说有点矫枉过正。我认为一个简单的模板方法模式也可以满足您的需求。但是,这取决于您要对查询结果执行的操作。这是一个模板方法示例:
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);
如果您需要为每个查询单独 returned 您可以将模板方法的 return 类型更改为 List<Map<String, String>>
.
据我了解,你好像不需要工厂模式。你可以有一个像下面这样的枚举:
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();
好吧,这道题主要有两点要实现。
- 引入并重新使用自定义查询逻辑。
- 将 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;
}
}
请注意,每个 子查询 class(例如:QueryA)应该是 Singleton 以避免内存占用。使用上面我们可以有自定义查询操作。
例如:QueryAB(事件 A 的需要)
@Inject
QueryA queryA;
@Inject
QueryB queryB;
Query queryAB = new CustomQuery(queryA, queryB);
现在您可以拥有一个 Map<String, Query> eventToQueryMap
动态 maps 您的 EventType 转化为必要的QueryLogic(s).
例如:
Map<String, Query> eventToQueryMap = new HashMap();
eventToQueryMap.put("EventA", queryAB);
eventToQueryMap.put("EventB", queryA);
//like above you can add for others too.
然后每当你收到你的事件类型字符串时,你都想做的是。
Map<String, String> eventMap = eventToQueryMap.get(eventType).execute(eventHolder);
这是您遇到的主要问题的大纲解决方案。您可以自己添加自定义。 :))
我有各种类型的事件,如下所示。总的来说我的活动比较多。
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" 作为事件类型,然后我将把 eventHolder Map 传递给一个方法(我们称之为 QueryA),在那个方法中,我会做在此地图上进行一些操作并 return 一个新地图。然后这个新的 Map 将被传递给另一个方法(让我们称之为 QueryB),然后我们将再次对其进行一些操作,然后 return 另一个 Map 然后该 map 将返回给调用者。
- 现在假设 "EventB" 在我的问题代码中作为 eventType 出现,然后我会将 eventHolder Map 传递给一个方法(我们称之为 QueryA),在该方法中,我会做一些在此地图和 return 新地图上进行操作。然后这张图会传回给调用者。
- 现在假设 "EventE" 在我的问题代码中作为 eventType 出现,然后我将把 eventHolder Map 传递给 EventE class,因为我们不需要为此做任何事情情况下,那么我将把这张地图传回给调用者。
问题:
对于这种问题,我应该使用哪种设计模式?我想避免使用 if/else 或在此处切换 bcoz 一般来说,我有很多事件类型,因此考虑为它们创建一个单独的工厂,我们可以通过传递 eventType 值在运行时动态加载它。
我事先知道所有的事件类型,所以我可以通过将它放在地图中来静态初始化所有工厂,然后一旦事件类型出现,而我们是 运行 代码,我可以从地图加载各个工厂.
如果这是解决此问题的正确设计模式,我如何在此处使用抽象工厂模式来完成此任务?我想将 "eventType"
作为键传递给工厂,该工厂将 return 该事件类型的实例。所以假设我将 "EventA"
传递给工厂,然后它将 return 工厂 class 传递给 "EventA"
,然后我们将在 class 上调用一个特定的方法它在内部调用 QueryA 方法,然后我们调用 QueryB 方法,最后它将 return 映射,我将在上面的代码中将其打印出来。其他事件类型也类似。
基于这个原因,我在想一些事情:我不确定工厂模式是否完全可行,或者是否可能是其他设计模式。 (我的命名约定可能搞砸了,我只是想出了下面的名字)
EventFactory eventFactory = EventTypeFactory.getInstance().getFactory(eventType);
Map<String, String> holder = eventFactory.execute(eventHolder);
我不确定我是否明白你的意思。您只需要一次工厂模式来初始化处理您的事件的对象。工厂是一种创建模式,与查询的执行无关。所以基本上你的方法是部分正确的:
Object o = EventTypeFactory.getInstance().getFactory(eventType);
这是可以使用工厂的地方。我故意使用 Object 作为类型,因为我们现在要讨论哪种模式最适合 "event handling"。首先它必须是一种行为模式。我会说命令模式可以派上用场。但是,您可能还需要迭代器模式来表示每个事件的潜在不同查询量。
然而,这样做对我来说有点矫枉过正。我认为一个简单的模板方法模式也可以满足您的需求。但是,这取决于您要对查询结果执行的操作。这是一个模板方法示例:
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);
如果您需要为每个查询单独 returned 您可以将模板方法的 return 类型更改为 List<Map<String, String>>
.
据我了解,你好像不需要工厂模式。你可以有一个像下面这样的枚举:
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();
好吧,这道题主要有两点要实现。
- 引入并重新使用自定义查询逻辑。
- 将 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;
}
}
请注意,每个 子查询 class(例如:QueryA)应该是 Singleton 以避免内存占用。使用上面我们可以有自定义查询操作。
例如:QueryAB(事件 A 的需要)
@Inject
QueryA queryA;
@Inject
QueryB queryB;
Query queryAB = new CustomQuery(queryA, queryB);
现在您可以拥有一个 Map<String, Query> eventToQueryMap
动态 maps 您的 EventType 转化为必要的QueryLogic(s).
例如:
Map<String, Query> eventToQueryMap = new HashMap();
eventToQueryMap.put("EventA", queryAB);
eventToQueryMap.put("EventB", queryA);
//like above you can add for others too.
然后每当你收到你的事件类型字符串时,你都想做的是。
Map<String, String> eventMap = eventToQueryMap.get(eventType).execute(eventHolder);
这是您遇到的主要问题的大纲解决方案。您可以自己添加自定义。 :))