我有一个文件解析器,它逐行读取文本文件并创建一个'事件'表示该行的对象。
有三种类型的'事件'所以我创造了4个pojos
EventTypeA
,EventTypeB
,EventTypeC
,EventTypeD
延伸BaseEvent
我推送到arraylist。
Pojos没有任何共同点,因为每个pojo(事件)都有不同的字段集。
现在我有一个事件处理程序,它应该根据类型处理列表中的所有事件。
我想用最优雅的方式来处理它们。我确定了四个选项:
instanceof
和投射
BaseEvent
具体到EventType
,但它并不优雅。type
字段(枚举)添加到pojo,然后执行
'开关'检查(+铸造),但它也不优雅。你能提出什么建议? 感谢
答案 0 :(得分:4)
这个问题有很多可能的解决方案。但是,你给出的限制会丢弃其中许多。我认为这里的主要问题是每次开发新的Event
类型时都试图避免修改现有代码。
一种可能的解决方案是在处理程序上使用 Chain of responsibility 。为处理程序定义一个通用接口:
interface EventHandler {
void handle(BasicEvent event);
}
您将为每种类型的事件提供具体的处理程序实现。然后,在通用处理器中收集所有事件。
class EventProcessor {
private List<EventHandler> handlers;
public EventProcessor(List<EventHandler> handlers) {
this.handlers = handlers;
}
public void process(BasicEvent event) {
handlers.forEach(handler -> handler.handle(event));
}
}
通过这种方式,每个事件只能由适当的处理程序处理。其他处理程序将丢弃该事件。每次开发新事件时,开发相对处理程序并将其添加到链中就足够了。
这种模式有很多变种。恕我直言,这是一个更简单的。
修改强>
为了完整起见,如果您可以删除您在
处说明的要求
- 第四个选项是创建一个hashmap,其中key是pojo类的名称,值是一个带有处理它的代码的class实例
醇>
我和其他人(请参阅下面的评论)认为最好的方法应该是为处理程序提供专用的Map
。
class EventProcessor {
private Map<EventType, EventHandler> handlers;
public void process(BasicEvent event) {
handlers
.get(event.getType)
.handle(event);
}
}
最重要的事实是上面的地图handlers
必须自动构建,可能使用依赖注入。这样,当您添加新类型的事件时,您可以保证不违反SOLID的 Open Closed Principle 。
干杯。
答案 1 :(得分:1)
您想要的模式是“访客”:
https://sourcemaking.com/design_patterns/visitor
我在我正在编写的解析器中使用它。我有一个抽象类“AbstractNode”,以及抽象语法树中每个节点类型的具体类(BinaryOperationNode,AssignStatementNode等)。我的解析器获取对树的根节点的引用,然后按顺序处理每个节点。访问者模式帮助我避免编写if instanceof / else if(...)的大量链。
缺点是每次创建新节点类型时都必须更新Visitor接口和实现它的每个类。
答案 2 :(得分:0)
由于您似乎主要担心的是将EventTypes与其处理程序分离,我会建议Chain of responsibility。
它通过在一系列潜在处理程序中传递EventType来管理解耦。
<强> Benfits 强>
<强>关注强>
不保证会有事件类型的处理程序。这可以通过 NotFound 处理程序来解决。