我正在做一个练习良好的设计/架构的游戏,我想我已将自己编程成一张支票。我不确定我的体系结构现在是否干净,请教一些建议。
我有一个class Game
,其中包含class GraphicsManager
class InputManager
和class StateManager
的实例
图形管理器与输入管理器一样处理sdl内容。状态管理器是抽象类型class GameState
每帧,游戏在状态堆栈顶部的GameState上调用更新,并将状态传递给StateManager指针,以便GameState可以推入新状态或从堆栈中弹出自身。
GameState* currentState = stateManager.getState() //return top
currentState.update(&stateManager) // state might change here
问题是当我介绍我的class Screen
时。 Screen应该归GameState的各种实现所有,因此,如果我拥有OpeningState,我希望它拥有OpeningScreen。
问题是,Screen需要访问Graphics实例才能获得指向SDL_Renderer的指针,但我看不到将指针向下传递的好地方。从Game-> GameState->屏幕传递指针感觉很时髦。
我觉得我需要将每个“经理”变成一个单例,但是如果有更优雅的东西,我想学习
这是我的编号为https://github.com/MicahMartin/FightingGame/tree/master/src的意大利面条
答案 0 :(得分:1)
您可以使用单例而不是显式地注入您的依赖项,但是请注意,这种设计会导致可测试性较低的代码以及组件之间的高功能耦合。其他生态系统已经解决了这个问题,这归功于框架提供了以“测试倍数”替换实际依赖关系的机制,从而以声明方式注入依赖项。了解Spring MVC如何与Java应用程序一起工作。
如果确定这是您所需要的,则可以使用类似(但仍不太灵活)的方法来实现“服务定位器”模式,该模式包含一个指向“可注入”对象实例的指针的点
ServiceLocator::inject<Screen*>(new Screen () , "screen1")
//
...
//
Screen* s = ServiceLocator::getInstance<Screen*>("screen1")
这样,您可以避免传递指针,同时避免更多的耦合。现在假设您有一个从Screen继承的MockScreen。还假设您要测试方法int MyClass :: workWithScreen(),该方法取决于使用标签“ screen1”引用的Screen实例。您可以像这样编写测试
Myclass unitUnderTest;
ServiceLocator::inject<Screen*>(new MockScreen () , "screen1");
int result = unitUnderTest.workWithScreen()
assert ....
我将留给您练习来实现服务定位器!
请记住,以这种方式,您在代码中还引入了依赖注入的缺点:最糟糕的是,您失去了对组件布局设计的控制,每个对象都可以访问每个对象。当您开发一些基于扎实且众所周知的架构模式的REST api处理程序时,这不是一个大问题(控制器->服务->存储库-> db,然后返回),但是在其他情况下您必须要小心!