在工厂类中使用单例(C ++)

时间:2018-06-19 04:28:24

标签: c++ singleton

我正在使用DirectX 11和C ++(使用默认的Visual Studio模板)开发游戏引擎,我有一些问题,我找不到在线答案。

因此游戏有三个主要组件,即实际游戏类,渲染器和逻辑类。游戏类看起来像这样

class Game {
    Game();
    ~Game();

    Logic* m_Logic;
    Renderer* m_Renderer
}

(如果你很好奇,我这样做有两个原因,1。为了解决课程问题,我之前已经按照传统的方式做了,所以我想尝试别的东西,看看它是否有任何真实的好的.2。以便两者的代码完全相互抽象)

我的问题是,如果将两个子类组成单例(假设是游戏类)是一个坏主意。我知道何时以及为何可以使用它们,但考虑到游戏类中只有一个实例,这可行吗?如果游戏类不是单身,并且可以同时运行多个副本(从而允许同时运行多个游戏,再次出于好奇心),该怎么办?

注意:因为每个人都在指出这一点。我知道他们不是个好主意。这是一个测试/实验。我正在进行有趣的编程。让我玩得开心:P

示例:当游戏类可以有多个实例时,我可能希望渲染器成为单例的示例。由于渲染器在游戏的不同实例之间是相同的,因此不需要存在多个实例。可以把它想象成所有函数的容器,它们只需要存储在游戏类中的各种变量,并将其输出到屏幕上。逻辑类也是如此。

1 个答案:

答案 0 :(得分:1)

有些人会说“单身人士永远不是一个好主意”,但直到今天,许多流行游戏引擎背后的工程师并未持有此声明。我会建议你尽可能减少它们的使用,但是会有适合它的情况。实际上,Jason Gregory在Naughty Dog上撰写的“游戏引擎架构”有一个关于它们用途的整个部分。我将举一个例子,我认为这是一种混合方法。

如果您仔细阅读虚幻引擎的代码库(或至少使用引擎),您会发现以下内容:

extern class UEngine * GEngine

UEngine实际上是所有Engine实现的基类(并且有多个因为需要不同的变体)。在启动期间,启动程序确定需要加载哪个变体,然后继续构造整个系统将使用的a single instance。这与您的方法类似,但您可以对初始化期间设置一次的Game对象进行全局引用,而不是制作多个Singletons:

extern std::unique_ptr<Game> game; // Global game reference in some .h file

(in .cpp)
std::unique_ptr<Game> game;
int main(int numArgs, char ** args) {
    game = std::make_unique<Game>( ... ); // Initialize game exactly once!!
    ...
}

这种方法可以让你做一些有趣的事情,特别是如果你让游戏成为像虚幻引擎所决定的工程师那样的界面,然后根据它背后的需要进行多次实现。

游戏维护的每个对象应该是单身人士吗?我不这么认为,因为它实际上限制了你以后可以做的事情。游戏至少需要支持以下内容:

  • 以正确的顺序创建,启动和关闭Logic和Renderer之类的东西(它拥有它创建的所有这些对象,因此与Game交互的所有代码都不可避免地与它们交互!)
  • 能够检索对Logic和Renderer等内容的引用,或者在可能的情况下保持隐藏,但提供有限的界面以获取对其功能的访问
  • 由于Game现在是你唯一的/唯一的全局变量之一,它成为你的引擎环境的网关,因此你可以做很多东西来封装它维护的组件而不是制作许多单例对象

我认为这比制作所有核心课程单身人士更好。