使用 Java 8 的排队方法



我正在构建一个游戏模拟器,其中包含数百个微步骤,如下所示。它们各自执行独特的任务,但为了简洁起见,我省略了实现细节。

public class Sim {
static void phase() {
phaseIn();
phaseOut();
}
static void untap() {
}
static void upkeep() {
}
static void draw() {
}
...
}

Turn通常涉及按顺序执行步骤,但有时特殊效果可能会导致顺序更改。例如,我可能需要重复一个步骤两次、跳过一个步骤或重新排列步骤的顺序。这些操作都是特殊情况,因为回合通常只是按从头到尾的顺序发生。

例如,以下一系列事件代表我的正常转弯。

>upkeep()>draw()>preCombatMain()> ...

现在,我玩一些需要我重复我的画步的东西。我需要轮到我看起来像这样:

>upkeep()>draw()>draw()>preCombatMain()> ...

轮到的步骤是方法,我不知道如何排队或取消排队的方法。我知道Java 8有方法引用,但功能相对较新。我一直无法将现有教程应用于我想要完成的任务。我得到了Sim::untap,但我不知道如何分配它,调用它等。如何在 Java 8 中对方法进行排队,或者按照玩家在运行时根据玩家所做的选择确定的顺序调用方法?

注意:我意识到我无法理解可能是由于一个根本的设计缺陷。我从来没有上过游戏设计课程,我完全愿意接受批评,如果有缺陷,我会改变我的设计。也就是说,这个问题不能被误解为"请推荐一种设计模式"。我考虑了一种替代设计,我在大量的 switch 语句中"编号"每一步,对"数字"进行排队,并在队列的前面反复切换,但这似乎是一个糟糕的计划(在我看来)。

如果您只是希望它们按顺序运行,您当然可以一个接一个地调用它们。如果顺序可以更改,另一种方法是使用方法引用队列:

LinkedList<Runnable> queue = new LinkedList<>();
queue.add(Sim::upkeep);
queue.add(Sim::draw);
queue.add(Sim::preCombatMain);
queue.forEach(Runnable::run);

我能够使用LinkedList<Runnable>,因为您的方法的签名void m().对于其他签名,您可以使用其他类型,例如:

  • void m()使用Runnable
  • T m()使用Supplier<T>
  • void m(T o)使用Consumer<T>
  • R m(T o)使用Function<T, R>

解决方案是使用多态性。为步骤定义接口:

interface Step {
void process();
}

然后通过实现来定义每个步骤:

class UpkeepStep implements Step {
void process() { ... }
}

现在,您可以将所有步骤放在一个数组中,根据需要对其进行随机播放,然后执行所有步骤,如下所示:

for (Step step : steps) {
step.process();
}

另一种可能运行得更快的方法是生成包含方法调用的代码,对其进行编译并加载类。但是,仅当与方法调用开销相比,该步骤不占用太多运行时,并且如果您大量执行每个生成的代码段,则 JIT 将对其进行优化,则它只会提供更好的性能。

最新更新