基本クラスから延期されたいくつかのクラスがありFile_plugin
ます。クラスのすべてのインスタンスに各クラスのインスタンスが必要です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
とを使用dynamic_cast
)。そのため、どこにでも電話をかけることはできませんget_plugin
。戻り値を保存して、高速アクセスに使用する必要があります。不快です。また、このソリューションは完璧に見えません。それを改善する方法はありますか?