单例管理器class,更好的设计?
A singleton-like manager class, better design?
我正在制作一个游戏引擎,我正在使用库来完成各种任务。例如,我使用需要初始化的 FreeType,获取管理器,在我不使用它之后,我必须取消初始化它。当然只能初始化一次,已经初始化过才能反初始化。
我想出了什么(只是一个例子,不是 "real" 代码 [但可能是有效的 C++ 代码]):
class FreeTypeManager
{
private:
FreeTypeManager() {} // Can't be instantiated
static bool initialized;
static TF_Module * module; // I know, I have to declare this in a separate .cpp file and I do
public:
static void Initialize()
{
if (initialized) return;
initialized = true;
FT_Initialize();
FT_CreateModule(module);
}
static void Deinitialize()
{
if (!initialized) return;
initialized = false;
FT_DestroyModule(module);
FT_Deinit();
}
};
对于我创建的每个管理器(FreeType、AudioManager、EngineCore、DisplayManager),它几乎是一样的:没有实例,只有静态的东西。我可以看出每次都重写这个框架可能是一个糟糕的设计实践。也许有更好的解决方案。
改用单例会好吗?或者是否有适合我的问题的模式?
如果你仍然想要单例方法(这对管理器类型的对象有意义),那么为什么不让它成为一个适当的单例,并有一个静态的get
函数,如果需要,创建管理器对象,并让管理器(私有)构造函数处理初始化并在析构函数中处理取消初始化(尽管管理器类型的对象通常具有整个程序的生命周期,因此析构函数只会在程序退出时调用)。
类似
class FreeTypeManager
{
public:
static FreeTypeManager& get()
{
static FreeTypeManager manager;
return manager;
}
// Other public functions needed by the manager, to load fonts etc.
// Of course non-static
~FreeTypeManager()
{
// Whatever cleanup is needed
}
private:
FreeTypeManager()
{
// Whatever initialization is needed
}
// Whatever private functions and variables are needed
};
如果您不想要单例,并且 class 中只有静态函数,您不妨使用 namespace
。对于变量,将它们放在实现(源)文件中的匿名命名空间中。或者对数据使用不透明结构指针(pimpl 惯用法 的变体)。
还有另一种解决方案,它不完全是单例模式,但非常相关。
class FreeTypeManager
{
public:
FreeTypeManager();
~FreeTypeManager();
};
class SomeOtherClass
{
public:
SomeOtherClass(FreeTypeManager &m) : m(m) {}
private:
FreeTypeManager &m;
};
int main() {
FreeTypeManager m;
...
SomeOtherClass c(m);
}
解决办法是让它保持普通的c++ class,但只是在main() 的开头实例化它。这会将 initialisation/destruction 移动到一个稍微不同的地方。您需要将对 FreeTypeManager 的引用传递给每个想要通过构造函数参数使用它的 class。
请注意,使用 main() 而不是其他函数很重要;否则你会遇到范围界定问题,需要思考如何处理..
我正在制作一个游戏引擎,我正在使用库来完成各种任务。例如,我使用需要初始化的 FreeType,获取管理器,在我不使用它之后,我必须取消初始化它。当然只能初始化一次,已经初始化过才能反初始化。
我想出了什么(只是一个例子,不是 "real" 代码 [但可能是有效的 C++ 代码]):
class FreeTypeManager
{
private:
FreeTypeManager() {} // Can't be instantiated
static bool initialized;
static TF_Module * module; // I know, I have to declare this in a separate .cpp file and I do
public:
static void Initialize()
{
if (initialized) return;
initialized = true;
FT_Initialize();
FT_CreateModule(module);
}
static void Deinitialize()
{
if (!initialized) return;
initialized = false;
FT_DestroyModule(module);
FT_Deinit();
}
};
对于我创建的每个管理器(FreeType、AudioManager、EngineCore、DisplayManager),它几乎是一样的:没有实例,只有静态的东西。我可以看出每次都重写这个框架可能是一个糟糕的设计实践。也许有更好的解决方案。
改用单例会好吗?或者是否有适合我的问题的模式?
如果你仍然想要单例方法(这对管理器类型的对象有意义),那么为什么不让它成为一个适当的单例,并有一个静态的get
函数,如果需要,创建管理器对象,并让管理器(私有)构造函数处理初始化并在析构函数中处理取消初始化(尽管管理器类型的对象通常具有整个程序的生命周期,因此析构函数只会在程序退出时调用)。
类似
class FreeTypeManager
{
public:
static FreeTypeManager& get()
{
static FreeTypeManager manager;
return manager;
}
// Other public functions needed by the manager, to load fonts etc.
// Of course non-static
~FreeTypeManager()
{
// Whatever cleanup is needed
}
private:
FreeTypeManager()
{
// Whatever initialization is needed
}
// Whatever private functions and variables are needed
};
如果您不想要单例,并且 class 中只有静态函数,您不妨使用 namespace
。对于变量,将它们放在实现(源)文件中的匿名命名空间中。或者对数据使用不透明结构指针(pimpl 惯用法 的变体)。
还有另一种解决方案,它不完全是单例模式,但非常相关。
class FreeTypeManager
{
public:
FreeTypeManager();
~FreeTypeManager();
};
class SomeOtherClass
{
public:
SomeOtherClass(FreeTypeManager &m) : m(m) {}
private:
FreeTypeManager &m;
};
int main() {
FreeTypeManager m;
...
SomeOtherClass c(m);
}
解决办法是让它保持普通的c++ class,但只是在main() 的开头实例化它。这会将 initialisation/destruction 移动到一个稍微不同的地方。您需要将对 FreeTypeManager 的引用传递给每个想要通过构造函数参数使用它的 class。
请注意,使用 main() 而不是其他函数很重要;否则你会遇到范围界定问题,需要思考如何处理..