0

开发模块化应用程序,我想在每个模块中注入一些帮助类。这应该自动发生。请注意,我的助手有状态,所以我不能只将它们设为静态并在需要的地方包含它们。

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

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 宏不太熟悉,所以我不知道他们是否能够做到这一点。

4

1 回答 1

1

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

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

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

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

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

以上都假设 helper 不依赖于模块(即它们处于较低的依赖抽象级别,对模块一无所知。)如果某些 helper 更接近于模块,也就是说,如果你开始想注入 module-on -module 相互依赖,上面的策略真的崩溃了。

在这些情况下(显然经常发生),我发现集中式ModuleManager单例(可能是全局对象)是最好的。您将模块显式注册到其中,以及显式的初始化顺序,它会构建所有模块。模块可以通过名称向此 ModuleManager 请求对其他模块的引用(有点像字符串到模块指针的映射),但它们会这样做一次,并以它们想要的任何方式在内部存储指针,以便方便和快速访问。

但是,为了防止混乱的生命周期和破坏顺序问题,每当一个模块被构造或破坏时,ModuleManager 都会通过回调通知所有其他模块,因此它们有机会更新其内部指针以避免悬空指针和其他问题。

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

于 2013-08-17T22:16:04.063 回答