如何在每个新模块中自动注入辅助类?

时间:2013-08-17 13:55:16

标签: c++ architecture macros module code-generation

开发模块化应用程序,我想在每个模块中注入一些辅助类。这应该是自动化的。请注意,我的帮助程序具有状态,因此我不能将它们设置为静态并将其包含在需要的位置。

我可以使用字符串键将所有帮助器存储在映射中,并使其可用于所有模块继承的抽象基类。

std::unordered_map<std::string, void*> helpers;
RendererModule renderer = new RendererModule(helpers); // argument is passed to
                                                       // base class constructor

然后在模块中,我可以访问这样的帮助器。

std::string file = (FileHelper*)helpers["file"]->Read("C:/file.txt");

但相反,我想像这样访问帮助者。

std::string file = File->Read("C:/file.txt");

为此,我现在单独为模块基类中的所有助手定义成员,并为每个特定模块设置它们。

FileHelper file = new FileHelper(); // some helper instances are passed to
                                    // multiple modules, while others are
                                    // newly created for each one
RendererModule renderer = new RendererModule();
renderer->File = file;

有没有办法自动化这个,这样我在向应用程序添加新助手时不必更改模块代码,同时保留第二种语法?我不熟悉C宏,所以我不知道他们是否有能力。

1 个答案:

答案 0 :(得分:1)

我看到你的困境是什么,但我没有很好的解决方案。但是,由于没有其他答案,我将贡献我的两分钱。

我使用一些策略的组合来帮助我解决这些问题:

  1. 如果帮助程序实例是真正特定于模块的,我让模块本身在其中创建和管理它。
  2. 如果我不希望模块知道帮助程序的创建或销毁,或者帮助程序实例的生命周期与使用它的模块没有关联,或者我想要共享在几个模块中的一个帮助器实例,我在外面创建它并将引用传递给模块的入口点构造函数。将它传递给构造函数具有使依赖显式化的优点。
  3. 如果帮助者的数量很高(例如超过2-3),我会创建一个包含所有指针的包含struct(或简单class)并传递该结构进入模块或子系统的构造函数。例如:

    struct Platform { // I sometimes call it "Environment", etc.
        FileHelper * file;
        LogHelper * log;
        MemoryHelper * mem;
        StatsHelper * stats;
    };
    

    注意:这不是一个特别好或安全的解决方案,但它并不比管理不同的指针更糟糕,而且很简单。

  4. 所有上述假设帮助程序不依赖于模块(即它们处于较低的依赖级别抽象,并且对模块一无所知。)如果某些帮助程序更接近模块,那么,如果您开始想要注入模块上的模块依赖关系,上面的策略真的崩溃了。

    在这些情况下(显然发生了很多)我发现集中的ModuleManager单例(可能是一个全局对象)是最好的。您明确地将模块注册到其中,以及显式初始化顺序,并构建所有模块。模块可以要求此ModuleManager按名称引用其他模块(类似于模块指针的字符串映射),但它们只执行一次并以任何方式在内部存储指针,以方便快速访问。

    但是,为了防止凌乱的生命周期和破坏顺序问题,无论何时构建或销毁模块,ModuleManager都会通过回调通知所有其他模块,因此他们有机会更新其内部指针以避免悬空指针和其他问题。

    就是这样。顺便说一句,您可能想要调查与“服务定位器”模式相关的文章和实现。