状态模式中字段注入的替代方案
Alternatives to field injection in state pattern
我正在开发一款游戏,游戏由介绍、菜单、加载、游戏等状态组成...这些状态由状态管理器交换(或放在彼此之上)在各州内部调用,因为每个州都有一个对管理器的引用,如下所示:
class IntroState extends State {
//....
void update() {
showIntro();
if(done) {
stateManager.swapState(new MenuState())
}
}
//....
}
我认为这是"state pattern",但如果我错了请指正。
某些状态与从平台特定模块发送到游戏核心模块的设置和输入配置等事物有一定的依赖性(例如,PC 平台有键盘控制,而移动平台有触摸控制),因此它们不是t 并且不应该是静态的。
最初我将这些依赖项作为构造函数参数并传递它们,但后来我 运行 遇到某些状态的情况,例如我的加载状态,它在加载资源时只呈现典型的加载屏幕,需要具有它们不使用的依赖项,因此可以将它们传递给确实依赖它们的状态。然后我添加的功能越多,依赖列表就会变得越大。
这看起来很糟糕,所以我创建了一个使用反射的 simple/naive 字段注入器,它可以工作,但是 android 上的反射非常慢,而且我不是特别喜欢反射。
我曾简要地考虑过 Dagger2 DI 框架,它不使用反射并保证稳定的性能,但注释生成的代码和繁重的汇编样板很快让我放弃了它。
因此,我正在寻找有关如何 send/request 我的状态的某些依赖项而没有构造函数混乱或基于反射的字段注入的建议。
我也遇到过这个问题,发现最简单的解决方案是最好的解决方案:将您所有的游戏服务集于一身class。
所以而不是这样:
State mainMenuState = new MainMenuState(inputService, renderingService, gameStateService);
State loadingState = new MainMenuState(renderingService, gameStateService);
// etc...
这样做:
State gameServices = new GameServices(inputService, renderingService, gameStateService);
State mainMenuState = new MainMenuState(gameServices);
State loadingState = new MainMenuState(gameServices);
// etc...
而 GameServices
看起来像这样:
public final class GameServices {
public final InputService inputService;
public final RenderingService renderingService;
public final GameStateService gameStateService;
public GameServices(final InputService inputService,
final RenderingService renderingService,
final GameStateService gameStateService) {
this.inputService = inputService;
this.renderingService = renderingService;
this.gameStateService = gameStateService;
}
}
我最初担心的是现在每种类型的州都可以访问每种游戏服务。然而,这在实践中从未被证明是一个问题;您的 IDE 可以在进行大的更改之前检查 class 的使用情况。
至于跨平台的逻辑,简单抽象到接口后面。因此,例如,'InputService' 在每个平台上可能有不同的实现。
游戏编程中最困难的部分之一是知道何时停止工程。请记住,您交付的是游戏,而不是库。 :)
我正在开发一款游戏,游戏由介绍、菜单、加载、游戏等状态组成...这些状态由状态管理器交换(或放在彼此之上)在各州内部调用,因为每个州都有一个对管理器的引用,如下所示:
class IntroState extends State {
//....
void update() {
showIntro();
if(done) {
stateManager.swapState(new MenuState())
}
}
//....
}
我认为这是"state pattern",但如果我错了请指正。
某些状态与从平台特定模块发送到游戏核心模块的设置和输入配置等事物有一定的依赖性(例如,PC 平台有键盘控制,而移动平台有触摸控制),因此它们不是t 并且不应该是静态的。
最初我将这些依赖项作为构造函数参数并传递它们,但后来我 运行 遇到某些状态的情况,例如我的加载状态,它在加载资源时只呈现典型的加载屏幕,需要具有它们不使用的依赖项,因此可以将它们传递给确实依赖它们的状态。然后我添加的功能越多,依赖列表就会变得越大。
这看起来很糟糕,所以我创建了一个使用反射的 simple/naive 字段注入器,它可以工作,但是 android 上的反射非常慢,而且我不是特别喜欢反射。
我曾简要地考虑过 Dagger2 DI 框架,它不使用反射并保证稳定的性能,但注释生成的代码和繁重的汇编样板很快让我放弃了它。
因此,我正在寻找有关如何 send/request 我的状态的某些依赖项而没有构造函数混乱或基于反射的字段注入的建议。
我也遇到过这个问题,发现最简单的解决方案是最好的解决方案:将您所有的游戏服务集于一身class。
所以而不是这样:
State mainMenuState = new MainMenuState(inputService, renderingService, gameStateService);
State loadingState = new MainMenuState(renderingService, gameStateService);
// etc...
这样做:
State gameServices = new GameServices(inputService, renderingService, gameStateService);
State mainMenuState = new MainMenuState(gameServices);
State loadingState = new MainMenuState(gameServices);
// etc...
而 GameServices
看起来像这样:
public final class GameServices {
public final InputService inputService;
public final RenderingService renderingService;
public final GameStateService gameStateService;
public GameServices(final InputService inputService,
final RenderingService renderingService,
final GameStateService gameStateService) {
this.inputService = inputService;
this.renderingService = renderingService;
this.gameStateService = gameStateService;
}
}
我最初担心的是现在每种类型的州都可以访问每种游戏服务。然而,这在实践中从未被证明是一个问题;您的 IDE 可以在进行大的更改之前检查 class 的使用情况。
至于跨平台的逻辑,简单抽象到接口后面。因此,例如,'InputService' 在每个平台上可能有不同的实现。
游戏编程中最困难的部分之一是知道何时停止工程。请记住,您交付的是游戏,而不是库。 :)