Pimplはバイナリ互換性に優れており、インターフェイスは実装を簡単に切り替えることができるのに適していることを読みました。これらの手法の両方を組み合わせて、アプリケーションが構成ファイルを介して基盤となる実装を切り替えることができるようにする必要があります。
これが私の現在のデザインのレイアウトです。
クラスFoo:クライアント向けAPIを提供します。ここではABIの互換性に関心があります
。クラスIFoo:インターフェイスクラス(すべての純粋仮想メソッド、仮想dtor)
クラスVendor1Foo:Vendor1のライブラリを使用してIFoo
を実装しますクラスVendor2Foo:Vendor2のライブラリを使用してIFooを実装します
pimplを使用せず、インターフェイスを厳密に使用すると、クライアントコードは次のようになります。
IFoo* foo = new Vendor1Foo();
問題は、私のクライアントコードがVendor1またはVendor2についてまったく知ることができず、Fooは私がこれを行わなければならない多くのクラスの1つにすぎないことです。
私がやろうとしていることの全体的な概念は次のとおりです。
class foo
{
private:
QScopedPointer<IFoo> pimpl;
void initImpl(); // Reads from QSettings and initializes pimpl
}
この問題のエレガントな解決策について何かアイデアはありますか?
これに対処する方法を標準化し、DRYの違反を最小限に抑えるために、いくつかのマクロまたはテンプレートクラス/メソッドを考え出すことを望んでいます。
テンプレートクラスは、ハーブサッターがC ++ 11の一般化されたpimplイディオムを採用するようなpimplヘルパーとして機能する可能性があります:herbsutter.com/gotw/_101また、構成に応じて正しい実装をインスタンス化するためのロジックが含まれている必要があります
ここには、pimplイディオム、ブリッジパターン、およびファクトリパターンの要素があります。上記の例では、initImpl()はファクトリメソッドと考えることができます。これらのパターンのすべてを使用する場合と使用しない場合があるソリューションを探しています。
私はすでにc++pimplイディオムを見てきました:テンプレートパラメータに応じた実装と、SOに関するほとんどのpimplイディオムの質問。タイトルは有望に見えましたが、私の特定のユースケースには役立ちませんでした。
C ++ 11を使用できず、Qtを使用しています。 Dポインターは単一の実装にバインドされているため、私の問題を解決しません。