如何避免对GUI背后的数据使用全局变量?
How do I avoid using a global for the data behind a GUI?
我正在编写一个音频处理独立应用程序。我有一个AudioManager
对象,它包装了与引擎有关的事情(例如I/O设备管理,信号处理路由,运行状态)。我正在写一个GUI来控制AudioManager
在后台运行。目前,每个需要向AudioManager
发送消息的组件都需要一个指向它的指针。
当一个深度嵌套的对象需要一个指向AudioManager
的指针时,这开始变得疯狂,因为这意味着我需要通过GUI对象的构造器传递指针,这些构造器不直接关心AudioManager
(只有一些子组件需要知道)。
我可以使AudioManager
成为单例以避免样板文件,但是来自类的信息流是双向的,所以这可能是一个坏主意。我也觉得把所有的东西都放在一个大的班级里有点可疑,但这让它更容易传递。有没有一个共同的模式来避免盲目的指针传递?
下面是一段伪代码,显示了一些构造函数,突出显示了问题的基本类型。我已经标记了这个c++ 11,看看它是否提供了任何独特的解决方案。
MainWindow()
{
am = new AudioManager();
someWidget = new SomeWidget(am);
}
SomeWidget(AudioManager* am_) //SomeWidget does not really care about am
{
someSubComponent = new SubThingy(am_);
}
SubThingy(AudioManager* am_) : subThingyLocalAudioManagerPtr(am_)
{
subThingyLocalAudioManagerPtr->registerSomethingOrOther(this);
}
在您的示例中," SomeWidget"应该采用其实际依赖项"SomeThingy ",而不是AudioManager。
通常当你看到整个世界都在引用一个类时,这意味着这个类做得太多了。名称"XyzManager"通常表示出于相同原因的问题。(类应该按照它们的功能来命名,如果描述它的功能的最具体的名称是"Manage",那么它应该是单独的类)
依赖注入可能有帮助。它还有助于清除所有权问题,并且您可以免费获得更好的可测试性,因为它使模拟类变得容易。
这个想法是把所有的资源分配给工厂;你的类函数只接受指向它们直接依赖项的(智能)指针。
下面的内容:
#include <memory>
using namespace std;
class SubThingy;
class AudioManager {
public:
void registerSomethingOrOther(SubThingy* st) { };
};
// None of the ctors do resource allocation
class SubThingy {
public:
SubThingy(AudioManager* am) : subThingyLocalAudioManagerPtr(am)
{
subThingyLocalAudioManagerPtr->registerSomethingOrOther(this);
};
private:
// raw pointer, we don't own it
AudioManager* subThingyLocalAudioManagerPtr;
};
class SomeWidget {
public:
// only takes DIRECT depencies
SomeWidget(unique_ptr<SubThingy> st) : someSubComponent(move(st)) { }
private:
// SomeWidget owns someSubComponent
unique_ptr<SubThingy> someSubComponent;
};
class MainWindow {
public:
// only takes DIRECT depencies
MainWindow(unique_ptr<SomeWidget> sw) : someWidget(move(sw)) { }
private:
// MainWindow owns its widgets
unique_ptr<SomeWidget> someWidget;
};
class Factory { // All memory allocations happen in the factory
public:
static unique_ptr<MainWindow> createMainWindow(AudioManager* am)
{
unique_ptr<SubThingy> someSubComponent{ new SubThingy(am) };
unique_ptr<SomeWidget> someWidget{ new SomeWidget(move(someSubComponent)) };
return unique_ptr<MainWindow>(new MainWindow(move(someWidget)));
}
};
int main() {
// not clear from the example who owns / should own the audio manager
AudioManager* am = nullptr;
auto mainWindow{ Factory::createMainWindow(am) };
}
现在,复杂性将显示在您的工厂类中,但至少混乱将被限制在一个地方。如果工厂变得太大,你可以把它分成单独的类;或者更好的是,有不同的工厂生产不相关的东西:一个工厂生产东西,另一个工厂生产小部件,等等。
我同意比利的观点,有一个经理在旁边是一个班级试图做得太多的标志,设计应该修改。不幸的是,如果God Object存在于第三方库中,而您无法控制它……(
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 当vector是tje全局变量时,c++中vector的内存管理
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 内联函数中具有内部链接的全局变量
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 全局变量 多读取器 一个写入器多线程安全?
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 不同作用域中的静态变量和全局变量
- C++ 在编译时具有函数计算全局变量
- 修改程序的入口点时未调用全局变量的构造函数
- 使用 std::ios_base::Init 正确初始化全局变量
- 为什么我的全局变量似乎没有变化?
- 将游戏数据加载到没有全局变量的池中
- (威纳皮C++)如何在没有全局变量的情况下将数据从一个窗口传递到另一个窗口
- C++:为什么与访问全局变量相比,访问类数据成员如此缓慢
- 如何避免对GUI背后的数据使用全局变量?
- 存储在全局变量中的数据与存储在堆中的数据有什么区别?
- C++SetConsoleCtrlHandler,在不使用全局变量的情况下传递用于清理的数据
- 决定数据存储和全局变量
- 如何在没有全局变量的情况下共享这些数据