我有几个从基类推迟的类File_plugin
。我想在 class 的每个实例中都有每个类的实例File
。这是一个天真的实现:
class File {
public:
File(): plugin1(this), plugin2(this), /*... */ {}
Plugin1 plugin1;
Plugin2 plugin2;
Plugin3 plugin3;
Plugin4 plugin4;
};
class File_plugin {
public:
File_plugin(File* p_file): file(p_file) {}
protected:
File* file;
};
class Plugin1: public File_plugin {
void some_action() {
//we can access another plugin as:
Plugin2* p2 = &( file->plugin2 );
}
};
但是File
类必须知道所有插件的实现是很糟糕的。我们通常在任何可能的地方都使用类的前向声明。所以,File
一定不知道插件的实现,甚至不知道类名的列表。一些插件会在运行时从 DLL 加载,所以我们在编译时不知道它们的名称。
此外,插件必须不知道几乎所有其他插件的存在。但是如果一个插件知道其他插件,它必须能够获取这个插件的对象并使用它。
现在我正在使用以下实现:
class File {
public:
File() : plugins(Plugins_registry::get_file_plugins(this)) { }
template<class T>
T *get_plugin() {
foreach(File_plugin *p, plugins) {
T* o = dynamic_cast<T*>(p);
if (o) return o;
}
throw Bad_exception(tr("File plugin not found"));
}
private:
QList<File_plugin*> plugins;
}
QList<File_plugin*> Plugins_registry::get_file_plugins(File* file) {
QList<File_plugin*> list;
list << new Plugin1(file);
list << new Plugin2(file);
list << new Plugin3(file);
list << new Plugin4(file);
//code below is untested
QPluginLoader loader("plugin5.dll");
list << dynamic_cast<My_plugin_class>(loader.instance)->get_file_plugin();
return list;
}
class Plugin1: public File_plugin {
void some_action() {
//we can access another plugin as:
Plugin2* p2 = file->get_plugin<Plugin2>();
}
};
一些插件可以存储在外部库中(在 Windows 上表示为 DLL)。它现在没有实施,但将来会实施。我认为我当前的实现允许这样做,但我没有检查。
这种实现的最大问题是插件搜索速度慢(使用for
and dynamic_cast
)。所以我不能只是get_plugin
到处调用,我必须存储返回值并将其用于快速访问。不舒服。此外,这个解决方案看起来并不完美。有没有办法让它变得更好?