1

我正在涉足编写多线程游戏结构。我下面是基本结构。EventManager、LogicManager 和 Renderer 都是线程。他们从一个通用的 Gamestate 类中读取/写入,该类将处理线程之间的所有共享资源。据我了解,Gamestate 在技术上应该是一个单例。那是对的吗?我还想知道如何将其实现为“早期初始化单例”,如下所述:http ://www.oodesign.com/singleton-pattern.html#early-singleton,C++除外。恐怕我不太精通 C++ 静态,因此我不知道将“私有静态 Singleton 实例 = new Singleton();”放在哪里 C++ 中的行。我知道我可以通过解决方法获得相同的效果,

int main(){
    Gamestate gs;
    EventManager em(&gs);
    LogicManager lm(&gs);
    Renderer renderer(&gs);

    lm.start();
    renderer.start();
    em.eventLoop();

    return 0;
}
4

2 回答 2

1

如果你绝对需要一个全局的游戏状态对象,那就让它成为全局的。将其声明为全局(智能)指针,在开头手动初始化,最后手动main销毁。通过这样做你

  1. 避免多线程问题
  2. 完全控制你的单例初始化和销毁​​的顺序
  3. 轻松注入模拟对象以进行单元测试

正如其他人指出的那样,单例被高估到成为反模式的地步。避免。

于 2012-12-07T08:42:47.257 回答
1

正如@juanchopanza 和@Dietmar 评论的那样,游戏状态确实没有理由应该是单例。

此外,我可以想到为什么它不应该是一个的几个原因:

  1. 单例使单元测试变得非常困难。模拟单例比模拟接口要困难得多。

  2. 假设有一天你想扩展你的游戏?例如,如果有一天你想让游戏逻辑在服务器上运行并让你的玩家运行客户端(想想多人游戏)怎么办?在这种情况下,您可能希望在您的流程中拥有多个游戏状态,并且单例会不必要地限制您。

  3. 如果你想对游戏状态做一些事情,比如序列化它以在机器之间发送,或者从文件中保存和加载它,让游戏状态成为单例会使它变得更加困难。使用标准的序列化框架变得很麻烦。

  4. 很难将依赖项注入到单例中。如果你需要一些组件或数据来初始化你的游戏状态怎么办?在这种情况下,您将在一段时间内某个线程可能会访问游戏状态实例,即使它处于不一致状态。

我可能会想到更多的原因。无论如何,我的建议是为所有组件定义接口,并让每个组件接收它所依赖的组件作为接口作为构造函数参数。

这使得编写良好解耦的类、防止类膨胀以及进行良好的单元测试变得更加容易。

然后,您可以使用任何反转控制框架在游戏初始化代码中自动将所有组件绑定在一起。

于 2012-12-07T08:21:31.847 回答