私はしばらくウェブを読んだり検索したりしてきましたが、良い解決策が見つかりませんでした。これが私がやりたいことです:
抽象基本クラスを定義するライブラリを作成しています - それをIFooと呼びましょう。
class IFoo {
public:
virtual void doSomething() = 0;
virtual ~IFoo() {}
};
ライブラリは、そのためのいくつかの実装も定義しています - それらをFooLibOneとFooLibTwoと呼びましょう。
作成プロセスをカプセル化し、ランタイム パラメータに応じてどの具体的な実装を使用するかを決定するために、std::string をファクトリ メソッドにマップするファクトリFooFactoryを使用します (私の場合は boost::function ですが、それは重要ではありません)。ここ)。また、新しいファクトリ メソッドを登録することもできます。次のようになります。
class FooFactory {
public:
typedef boost::function<IFoo* ()> CreatorFunction;
IFoo* create(std::string name);
void registerCreator(std::string name, CreatorFunction f);
private:
std::map<std::string, CreatorFunction> mapping_;
};
今のところ、ライブラリによって提供される実装 (FooLibOne、FooLibTwo) をFooFactoryのコンストラクターに直接追加しました。したがって、それらは常に利用可能です。一部のライブラリ コードは特定のオブジェクトなどを初期化するために FooFactory を使用します。ティー パターンは頻繁に議論され、Singleton パターンのさまざまな実装がどのように機能するか確信が持てなかったため、これまでのところ、ファクトリに Singleton パターンを使用することは控えてきました。おそらく複数の共有ライブラリなどと組み合わせて。
ただし、工場を回るのは少し面倒な場合があり、これは Singleton パターンが役立つ機会の 1 つだと思います。特に、ライブラリのユーザーは、(既存の) ライブラリコードからもアクセスできるIFooの実装をさらに追加できる必要があると考えています。もちろん、依存性注入 (つまり、コンストラクターを介してファクトリのインスタンスを渡すことを意味します) は、そのトリックを行うことができます (そして、今のところ実行しています)。しかし、さらに柔軟になり、動的オブジェクト作成の第 2 層を導入したい場合、このアプローチは失敗します。意味: 動的に作成されたオブジェクト (抽象基本クラスIBarの実装- BarOneおよびBarTwo - 再びファクトリBarFactory経由)。
BarOneにはIFooオブジェクトが必要ですが、 BarTwoには必要ないとしましょう。IBar実装の 1 つがそれを必要とする可能性があるため、いずれにせよ、BarFactory にFooFactoryを提供する必要があります。グローバルにアクセス可能なファクトリがあれば、この問題は軽減され、特定のインターフェイスの実装でどのファクトリが必要になるかを予測する必要はありません。さらに、作成メソッドを実装のソース ファイルに直接登録することもできました。
FooFactory::Instance().registerCreator("new_creator", boost::bind(...));
それは良い考えだと思うので、それを実装する正しい方法は何でしょうか? ファクトリをラップするために、Modern C++ Design ( Lokiライブラリも参照) のSingletonHolderのようなテンプレート化されたアプローチを使用していました。ただし、代わりにマイヤーのシングルトンとして実装したいと思います。しかし、共有ライブラリにはまだ問題があると思います。このソリューションは、GCC (およびできれば MSVC) で動作するはずです。私はデザインの観点から他のアイデアにもオープンですが、よくある「シングルトンは悪だ」という暴言は避けてください。;-)
前もって感謝します。