2

好的,我有一个运行在 Java/Hibernate/Spring/Quartz 中的游戏服务器。游戏时钟与 Quartz 计时器一起滴答作响,效果很好。

然而,我还有许多其他事情需要在特定的、可调整的时间间隔内发生(在游戏时间,而不是实时)。

例如,每 24 小时游戏时间(约 47 分钟实时,取决于服务器时钟倍数)就会发生一堆不同的一天一次的游戏动作,比如补给,或者你有什么。

现在,当前系统非常粗糙,但是可以工作 - 我在数据库中有一个表,它本质上是一个 cron - 一个字符串键,下一个事件的执行时间,然后是小时、分钟、秒和天,直到下一个事件. 时间记录器会检查这一点,然后将包含该代码(事件字符串键)的消息发送到队列中,将天、分钟、秒添加到当前时间并将其设置为下一个执行时间。

消息监听器是最重要的部分——它打开按键并点击它的一种方法。

现在我明白这可以很好地工作,但它真的不适合我。你的解决方案是什么,让每段代码都放在自己的小类中?什么设计模式涵盖了这个?(我确定有一个)。我有一些想法,但我想听听一些意见。

4

5 回答 5

1

您可以使用散列表来调度这些事件,而不是打开密钥。这样,您的计时器事件就不需要相互了解。

应该有可能有类似的东西:

timerQueue.registerHandler("key",new TimerHandler(){
   // do something timer related  
});

这样,您可以重新启动 java 代码处理事件,而不会丢失持久的事件队列。

http://en.wikipedia.org/wiki/Priority_queue'>如果您还没有,优先队列值得一看。

于 2009-03-30T20:59:04.423 回答
1

我会使用Command Pattern. 我会扩展命令模式来创建一个 IIntervalCommand 类。除了 Execute 方法之外,它还有一个 interval 属性和一个只读 CanExecute 属性。

然后创建一个包含 IIntervalCommand 列表的 CommandList 类。它将有一个名为 CheckToExecute 的方法,您可以将当前游戏时间传递给它。CheckToExecute 方法将遍历为每个命令调用 CanExecute 的列表。如果经过的时间已经过去,CanExecute 将返回 true。如果 CanExecute 返回 true,则 CheckToExecute 将调用实现 IIntervalCommand 的对象的 Execute 方法。

然后添加额外的游戏事件就是创建一个实现 IIntervalClass 的新类。实例化对象并将其添加到 IntervalCommandList。

如果事件的处理很耗时,那么该命令可以将处理作为单独的线程产生。即使间隔再次过去,它也会向其 CanExecute 属性返回 false ,直到线程返回。或者,如果间隔再次过去,你让它产生另一个线程。

你避免了巨大的案例陈述。您可以在实例化对象时消除数据库并设置参数。或者保留它并将其用作创建所有 IIntervalCommands 的工厂的一部分。

于 2009-03-30T19:22:09.523 回答
1

您可以将代码用作映射中的键,而不是打开一组代码,其中值是实现处理程序接口的对象。这使您可以更加灵活地添加新的事件类型。

该模式看起来像这样:

private final Map<String, Handler> handlers = new TreeMap<String, Handler>();

public void register(String event, Handler handler) { 
  handlers.put(event, handler); 
}

public void handle(String event) {
  Handler handler = handler.get(event);
  if (handler == null) {
    /* Log or throw an exception for unknown event type. */
  }
  else {
    handler.execute();
  }
}

您可以使用 Java 6 之类的东西来添加新行为,而不是显式注册处理程序,ServiceLoader只需将 JAR 放到类路径中即可。

于 2009-03-30T18:30:35.420 回答
0

从概念上讲,我认为您正在做两件事;

首先,您有一个缩放版本的time。只要这个时间和挂钟时间之间的关系保持不变,我很确定我只是将这种缩放行为委托给一个类,它会有像这样的签名

DateTime getFutureTime( VirtualTimeSpan timespan)

我将使用它来将虚拟时间跨度映射到实时实例。此后您可以实时操作,这可能会简化一些事情,因为您可以使用标准调度功能。

第二部分关于为未来的工作进程安排工作。有许多核心技术与此相关;从概念上讲,我认为JMS是其中许多的 Java 祖父,它定义的概念与您正在使用的概念和您需要的概念非常相似。我认为查看 JMS 可以很好地了解您可能会感兴趣的概念,它使用选择器将任务发送给特定的工作人员,就像您描述的工作人员一样。

唉,JMS 似乎从来不适合大多数人。很多人发现它过于重量级或实现过于错误。所以通常人们最终会使用自制的队列技术。但是概念都在那里。你不能只用石英吗?

于 2009-03-30T18:37:59.147 回答
0

我个人不会把它放在数据库中,而是让一个单独的服务在后台运行。然后我的 Web 服务或 Web 应用程序将通过进程间通信与该服务进行通信。不知道这如何转化为 java 世界。

于 2009-03-30T18:13:58.253 回答