使用混合POJOS处理集合,为每个POJO使用不同的处理程序

时间:2009-04-21 10:39:28

标签: java language-agnostic design-patterns

我正在尝试为以下问题找到一个优雅的OOP解决方案。

假设我们有一个POJOS集合,在这种情况下是事件,其中每个POJO可能是不同的类。我们需要为每个POJO类(或类型)使用不同的规则来处理此集合。

一个基本的假设是我们不能用适当的处理程序来装饰POJO,因为我们不控制它们的生成,并按原样接收集合。因此,任何机制都属于同一个陷阱。但是,第3项目仍处理这种可能性。

有一些可能的解决方案,一些非常难看,一些更优雅但很复杂:

  1. 显而易见的解决方案,也是最丑陋的,正在使用instanceOf运算符将POJO传递给处理程序。
  2. 稍微好一点的修改1是使用链式调度程序对此负责,因此新类型只需要一个新的调度程序。但是,每个调度程序仍然需要instanceOf。
  3. 创建增强对象,而不是POJOS,其中每个对象都包含对其处理程序的引用。这在POJO和我们的处理器之间创建了耦合。
  4. 创建(我知道如何在Java中正确执行此操作)一个调度程序服务,它将处理程序注册到特定的事件类,并使用泛型(Typesafe容器,如在有效的java中)将事件分派给处理程序。
  5. 4是最优雅的,但我想知道是否有更好的想法。

5 个答案:

答案 0 :(得分:4)

简化#4:

使用Map存储每个事件类的处理程序。

Map<Class, Handler> classHandlers = new HashMap<Class, Handler>();
classHandlers.put(EventA.class, new EventAHandler());
classHandlers.put(EventB.class, new EventBHandler());

现在使用事件的类来获取事件的处理程序。

Handler handler = classHandlers.get(event.getClass());
handler.handle(event);

当然,这需要在编码时了解所有可能的事件类,因此不如外部事件调度程序灵活。

答案 1 :(得分:1)

  

假设我们有一个POJOS集合,在这种情况下是事件,其中每个POJO可能是不同的类。我们需要使用针对每个POJO类(或类型)的不同规则来处理此集合。

祝贺如果POJO类稳定(通常不会添加新的类类型),您刚刚描述了使用访问者模式的动机!

更好的是,因为你可能想要对你的POJO集合做不同的事情,你可以创建一个AbstractBaseVisitor并扩展它来处理你需要做的不同的事情!

这将需要在每个POJO周围放置一个小包装器,每个POJO类有一个包装器类,以添加一个回调给访问者的visit()函数。

答案 2 :(得分:0)

我在这个场景中使用过4号解决方案,我觉得它很好。我还会就更好的解决方案寻找其他意见。

答案 3 :(得分:0)

4是您提供的最佳解决方案。 #1&amp;因为乱七八糟的实例,所以2会很痛苦。

另一个解决方案:使用它的调度程序方法注释每个类。您不需要中心位置来处理调度程序调用,并且POJO /调度程序不会在注释之外耦合。

答案 4 :(得分:0)

问题实际上根本不是语言不可知论者。在某些语言中,您可以轻松地装饰类。但是,让我们坚持使用Java。即使在那里,我说“这取决于”。

我们想要做的一件明显的事情是处理程序的某种自动发现。例如,使用@Handler(handles = PojoA.class)注释来注释处理程序,然后扫描所有使用@Handler注释的类(基本上需要加载类文件或使用类似Scannotation之类的杂乱方式)。 / p>

如果您在Spring等环境中运行,则会出现更有趣的选项。您可以获取实现特定接口的所有bean,例如:

public interface Handler<T> {
    void handle(T object);
}

然后在您的调度程序代码中找到它们:

Collection<Handler> handlers = applicationContext.getBeansofType(Handler.class).values();
for (Handler handler : handlers) {
    Method handleMethod = handler.getClass().getMethod("handle", Object.class);
    Class<?> type = handleMethod.getParameterTypes()[0];
    register(type, handler);
}

(诚然,上面的代码未经测试)

我意识到我走出了界限。我的观点是,解决方案的优雅取决于您选择的语言,您愿意使用的外部工具以及您正在使用的框架。