开发一个模块化的应用程序,我想在每个模块中注入(inject)一些帮助类。这应该自动发生。请注意,我的助手有状态,所以我不能只将它们设为静态并在需要的地方包含它们。
我可以将所有助手存储在一个带有字符串键的映射中,并使其可供所有模块继承自的抽象基类使用。
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 宏,所以我不知道它们是否能够做到这一点。
最佳答案
我认为我明白你的困境是什么,但我没有好的解决方案。但是,由于没有其他答案,我将贡献我的两分钱。
我结合使用了一些策略来帮助我解决这些问题:
- 如果助手实例确实是特定于模块的,我会让模块本身在内部创建和管理它。
- 如果我不想让模块知道助手的创建或销毁,或者如果助手实例的生命周期与使用它的模块无关,或者如果我想共享几个模块中的一个助手实例,我在外部创建它并将引用传递给模块的入口点构造函数。将其传递给构造函数的好处是可以显式依赖。
如果助手的数量很多(比如超过 2-3 个),我会创建一个包含所有内容的
struct
(或简单的class
)指针并将该结构传递给模块或子系统的构造函数。例如:struct Platform { // I sometimes call it "Environment", etc. FileHelper * file; LogHelper * log; MemoryHelper * mem; StatsHelper * stats; };
注意:这不是一个特别好的或安全的解决方案,但它并不比管理不同的指针差,而且很简单。
以上都是假设helpers不依赖于模块(即它们处于较低的依赖级别抽象并且对模块一无所知。)如果一些helpers更接近于模块,也就是说,如果你开始想要注入(inject)模块对模块的相互依赖,上述策略真的崩溃了。
在这些情况下(显然经常发生),我发现集中式 ModuleManager
单例(可能是全局对象)是最好的。您显式地将您的模块注册到其中,以及 显式 初始化顺序,它会构建所有模块。模块可以通过名称向此 ModuleManager 请求对其他模块的引用(有点像字符串到模块指针的映射),但它们只执行一次并以它们想要的任何方式在内部存储指针,以便方便和快速访问。
但是,为了防止困惑的生命周期和销毁顺序问题,任何时候构建或销毁模块时,ModuleManager 都会通过回调通知所有其他模块,因此它们有机会更新其内部指针以避免悬空指针和其他问题。
就是这样。顺便说一下,您可能想要研究与“服务定位器”模式相关的文章和实现。
关于c++ - 如何在每个新模块中自动注入(inject)辅助类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18289576/