8

我正在编写一个音频处理独立应用程序。我有一个AudioManager对象,它包装了与引擎有关的事情(例如 I/O 设备管理、信号处理路由、运行状态)。我正在编写一个 GUI 来控制AudioManager后台运行。目前,每个需要发送消息的组件都AudioManager需要一个指向它的指针。

当一个深度嵌套的对象需要一个AudioManager指向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);
}
4

2 回答 2

8

在您的示例中,“SomeWidget”应该采用其实际依赖项“SomeThingy”,而不是 AudioManager。

通常,当您看到整个世界都在引用一个类时,这意味着该类做的太多了。出于同样的原因,名称“XyzManager”通常表示存在问题。(类应该以它们的作用命名,如果描述它作用的最具体的可用名称是“管理”,那么它应该是单独的类)

于 2013-06-20T20:28:35.077 回答
2

依赖注入可能会有所帮助。它还有助于清除所有权问题,并且您可以免费获得更好的可测试性,因为它可以轻松模拟类。

这个想法是将所有资源分配转移到工厂;您的类 ctor 仅采用(智能)指向其直接依赖项的指针。

这些方面的东西:

#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) };
}

现在,复杂性将出现在您的工厂类中,但至少混乱将被限制在一个地方。

如果工厂变得太大,您可以将其拆分为单独的类;甚至更好的是,有不同的工厂来生产不相关的东西:一个生产东西的工厂,另一个生产小部件的工厂,等等。

我同意比利的观点,有一个经理在身边是一个班级试图做太多事情的标志,应该修改设计。不幸的是,如果上帝对象存在于第三方库中并且您无法控制它... :(

于 2013-06-20T21:03:01.320 回答