我有各种类型的活动,如下所示。一般来说,我有更多的活动。
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 ----->
问题:
我应该使用哪种设计模式来解决这类问题?我想避免使用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);
答案 0 :(得分:1)
嗯,在这个问题上有两件事要做。
首先我喜欢你 采用 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 ,以避免记忆足 - 打印。使用上面我们可以进行自定义查询操作。
ex:QueryAB(需要eventA)
@Inject
QueryA queryA;
@Inject
QueryB queryB;
Query queryAB = new CustomQuery(queryA, queryB);
现在,您可以拥有Map<String, Query> eventToQueryMap
动态 地图 EventType < em>进入 必要的 QueryLogic 。
前:
Map<String, Query> eventToQueryMap = new HashMap();
eventToQueryMap.put("EventA", queryAB);
eventToQueryMap.put("EventB", queryA);
//like above you can add for others too.
然后,只要您收到eventType字符串,您想要做的就是。
Map<String, String> eventMap = eventToQueryMap.get(eventType).execute(eventHolder);
这是您遇到的主要问题的大纲解决方案。您可以自己添加自定义。 :))
答案 1 :(得分:0)
我不确定我是否理解你的观点。您只需要一次工厂模式来初始化处理事件的对象。 Factory是一种创建模式,与查询的执行无关。所以基本上你的方法是部分正确的:
Object o = EventTypeFactory.getInstance().getFactory(eventType);
这是可以使用工厂的地方。我故意使用Object作为一种类型,因为我们现在要讨论哪种模式最适合&#34;事件处理&#34;。首先,它必须是一种行为模式。我会说Command模式可以派上用场。但是,您可能还需要Iterator模式来表示每个事件的可能不同的查询量。
然而,这样做对我来说有点矫枉过正。我认为一个简单的模板方法模式也会产生你需要的东西。但是,这取决于您要对查询结果执行的操作。这是一个Template方法示例:
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);
如果您需要单独返回每个查询的每个Map,您可以将模板方法的返回类型更改为List<Map<String, String>>
。
答案 2 :(得分:0)
据我了解你,你似乎不需要工厂模式。你可以像下面这样的枚举:
import Foundation
let data = Data(bytes: [24, 163, 209, 194, 255, 1, 184, 230, 37, 208, 140, 201, 6, 0, 64, 0, 7, 98, 108, 117])
let dataStream = InputStream(data: data)
dataStream.open()
let numBytesPerObject = 2
var buffer = [UInt8](repeating: 0, count: numBytesPerObject)
while dataStream.read(&buffer, maxLength: numBytesPerObject) != 0 {
print(buffer)
}
使用以下就足够了:
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() {
}
}