如何避免对GUI背后的数据使用全局变量?

How do I avoid using a global for the data behind a GUI?

本文关键字:全局变量 数据 何避免 GUI 背后      更新时间:2023-10-16

我正在编写一个音频处理独立应用程序。我有一个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存在于第三方库中,而您无法控制它……(