建模事件类型对象

时间:2015-04-23 10:15:57

标签: java oop events

我们有一个由许多独立组件和子系统组成的应用程序。我们正在寻求实现一个简单的事件记录机制,其中这些组件和子系统可以记录一些感兴趣的事件。事件可能类似于

  • 已创建新帐户
  • 航班抵达
  • 每周报告发送给管理层等。

如您所见,事件类型本质上是异构的,需要记录的属性因事件类型而异。例如,新帐户创建的活动还将记录帐户ID,创建新帐户的用户的名称等。然而,航班到达事件将记录航班号,到达,到达等等。

我想知道对事件类型和属性建模的好方法是什么。

一种选择是以面向对象的方式 - 使一个AbstractEvent具有一些共同的属性(时间戳,消息等),然后在下面创建一个完整的类层次结构。例如,航班事件可能看起来像

abstract class AbstractEvent;
abstract class FlightEvent extends AbstractEvent;
class FlightArrivedEvent extends FlightEvent;
class FlightCancelledEvent extends FlightEvent;

我看到这个approch的问题是我们有数百个事件会导致类爆炸。此外,每当我们添加一个新事件(很可能)时,我们必须创建一个类并将新包分发给所有组件和子系统。

我能想到的第二个选择是在光谱的另一端。有一个简单的Event类,它包含基本属性并在其中包含一个映射,以便客户端可以填充他们想要的任何数据。在这种情况下的代码看起来像这样。

class Event {
    private timestamp;
    private eventType;
    private Map attributes;

    public Event ( String eventType ) {
        timestamp = System.nanoTime();
        this.eventType = eventType;
        attributes = new HashMap();
    }

   public Event add ( String key, String value ) {
        attributes.put ( key, value );
        return this;
   }
}
//Client code.
Event e = new Event("FlightEvent:FlightArrived")
         .add("FLIGHT_NUMBER", "ABC123")
         .add("ARRIVED_AT", "12:34");

虽然这很灵活,但却存在不一致之处。两个组件可以以两种不同的格式(FLIGHT_NUMBER& FLGT_NO)记录FLIGHT_NUMBER键,我无法想出执行某些约定的好方法。

任何人都有一些建议可以在这两个极端选项之间提供一个很好的折衷方案吗?

3 个答案:

答案 0 :(得分:1)

有一个Java事件框架(请参阅java.util.EventObject和Beans框架),但您要问的基本问题与事件无关。这是一个设计问题,它是这样的:我在我的应用程序中使用Java类来表示业务领域中的类吗?

很明显,不同类型的事件是事物的不同“类”,但出于可维护性原因,您正在考虑在地图中表示业务数据,这样您就不必编写和分发实际的类。如果你把它带到一个逻辑极端,你可以设计你的整个应用程序没有类,只需使用地图和名称 - 值对的一切 - 而不仅仅是事件。这将是一个混乱,你会永远调试它,因为你没有任何类型安全。找到地图中的内容的唯一方法是在某些文档中查找某人可能添加到其中的内容以及该对象可能是什么类型。

所以,这就是事情 - 你实际上没有摆脱你的班级定义

您将把它移动到人们必须引用的某个Word文档中,以便了解地图中的内容。 Word文档需要维护,验证和分发,但与Java类不同,编译器不会对其进行检查,也无法保证程序员能够正确解释它。

所以我想说,如果有一个类,将它放在你的代码中,然后专注于解决分发和版本化Java类的问题,而不是分发和版本化Word文档。

我会再次提到版本控制,因为如果您可以序列化对象并将其恢复,这是一个问题,因此您需要考虑这一点。

一些警告:

  1. 如果您正在编写一个将事件从一个系统路由到另一个系统的中间件软件,那么您可能不需要知道关注数据是什么,并且可能有意义使用在这种情况下通用持有人。如果您不需要查看数据,则不需要它的类。

  2. 与地图和名称/价值相比,您可能会收到高级设计师和架构师关于课程数量和他们在定义课程时必须完成的工作的投诉。这是因为在Java中放置类(即真实设计)比将它们放在Word文档中更难。如果你是高级易挥手型的家伙,更容易在Word中编写一些不需要运行甚至编译的东西,然后将真正的设计工作交给程序员开始工作。

答案 1 :(得分:0)

  

[某人]可以在这两个极端选项之间提供一个很好的折衷方案吗?

没有。这个问题没有通用的“一刀切”的答案。您必须找到适合您产品的一般设计的天平。如果你把一切都搞定了,你将需要数千个课程。如果你给予很多回旋余地,你可以侥幸逃脱,但是你需要精确地支付你的自由。请参阅我的博文" Designing a Garbage Bin"

你有共享属性吗?如:你期望定义事件的属性,就像你现在用非常紧密的语义定义类一样?

这意味着你有一个简单的事件和类型属性(即String value根本就不够)。您需要格式化和验证属性或...属性本身需要是类。

如果是这种情况,您可以使用我的类型安全的地图模式:http://blog.pdark.de/2010/05/28/type-safe-object-map/

答案 2 :(得分:0)

事件类型"爆炸"不是问题。实际上,这是一种理想的方法,因为它允许组件彼此独立。我不一定会让所有事件都从一个超类继承,除非它给你很多可重用的代码,因为它可能导致依赖开始激增。

我会将事件类型放在一个单独的项目中,该项目将是发布者和消费者的依赖。

组件之间这些事件的通信机制是什么? JMS?如果是这样,您还可以考虑将消息XML和使用JAXB。

我肯定会打破地图方法,因为它会破坏多态性或任何其他oo niceties的任何希望。