遇到一个问题,我正在寻找最佳的解决方案概念/理论。
我有一个需要使用对象的系统。系统使用的每个对象都有一个已知的接口,可能实现为抽象类。接口在构建时已知,并且不会更改。要使用的确切实现方式会有所不同,我不知道哪个模块会提供它。唯一的保证是他们将提供界面。类名和模块(DLL)来自配置文件,或者可以通过编程方式进行更改。
现在,我已经使用一个相对简单的系统设置了所有这些,设置了类似的东西(重写的伪代码,只是为了显示基础知识):
struct ClassID
{
Module * module;
int number;
};
class Module
{
HMODULE module;
function<void * (int)> * createfunc;
static Module * Load(String filename);
IObject * CreateClass(int number)
{
return createfunc(number);
}
};
class ModuleManager
{
bool LoadModule(String filename);
IObject * CreateClass(String classname)
{
ClassID class = AvailableClasses.find(classname);
return class.module->CreateObject(class.number);
}
vector<Module*> LoadedModules;
map<String, ClassID> AvailableClasses;
};
模块有一些导出的函数来提供它们提供的类的数量以及那些存储的类的名称/ ID。所有类都派生自IObject
,它有一个虚拟析构函数,存储源模块,并有一些方法来获取类的ID,它实现的接口等等。
唯一的问题是每个模块都必须在某处手动加载(此时在配置文件中列出)。我想避免明确地这样做(在ModuleManager
之外,我并不真正关心它是如何实现的。)
我希望有一个类似的系统,无需处理加载模块,只需创建一个对象,并且(一旦设置完毕)它就会神奇地出现。
我认为这在某些方面类似于COM的目的。我简要地研究了COM系统,但它似乎有点超乎想象。我只需要系统中已知的类,不需要它处理的所有其他功能,只需要来自某个地方的接口实现。
我的另一个想法是使用注册表并保留一个密钥与所有已知/已注册的类及其源模块和数字,所以我可以查找它们,看起来Manager::CreateClass
找到并生成对象神奇地。这似乎是一个可行的解决方案,但我不确定它是否是最佳的,或者我是否正在重新发明一些东西。
所以,毕竟,我的问题是:如何处理?是否有现有技术,如果没有,如何最好地自己设置?有什么问题我应该留意吗?
答案 0 :(得分:1)
我不知道是否有任何技术可以做到这一点。
我知道我使用的系统非常类似于此。我们使用XML文件来描述不同模块可用的各种类。我们相当于ModuleManager将解析xml文件,以确定在运行时根据用户提供的类名和系统配置为用户创建的内容。 (请求实现接口'I'的对象可以根据系统的配置方式返回任何对象'A','B'或'C'。)
我们发现的最大问题是系统非常脆弱,有时难以调试/理解。只是阅读代码,通常几乎不可能看到实例化的具体类。我们还发现维护XML会产生比预期更多的错误和开销。
如果我再次这样做,我将保留从DLL通过接口暴露类的设计模式,但我不会尝试构建类的中央注册表,也不会从基类如IObject派生所有内容
我会让每个模块负责公开自己的工厂函数来实例化对象。
答案 1 :(得分:1)
COM非常可能是你想要的。它非常广泛,但您不需要使用所有功能。例如,您不需要参与者注册GUID,您可以定义自己的机制来创建接口实例。有许多模板和其他机制可以轻松创建COM接口。更重要的是,由于它是标准,因此很容易记录要求。
要记住的一件非常重要的事情是导入/导出C ++对象需要所有参与者使用相同的编译器。如果您认为对您来说可能是个问题,那么您应该使用COM。如果您乐意接受这一限制,那么您可以继续保持原样。