5

私は実際には複雑ではないデザインの問題を抱えていますが、それを解決するためのエレガントな方法を見つけたいと思います。そして私はこれについて考えました:

問題:Bのコレクションを初期化して保持するクラスAがあります

Bは単なるインターフェースであり、実装する必要があります(したがって、クラスC、D、E、..があります)。

コンストラクターでAは大量のデータセットを受け取り、各データセットを指定してBの一部(同じクラスまたは異なるクラスの多くの異なるインスタンス化)を初期化する必要があります。AにBの実装を知らないようにしたいと思います。

私にはいくつかの実用的な解決策がありますが、私は一種の「コンストラクターでの委任」について考えていました。例えば:

1. for each dataset, ds
2.   for each implementation of B, bi
3.     try to instantiate bi(ds)
4.       if success (means no exception)
5.         keep reference

これは、biが初期化とパフォーマンスが重要なアプリケーションにあるかどうかを確認するために使用するデータと計算が、それを2回実行したり、コレクションクラスで実行したりすることを避けたいためです。
それは本当に素晴らしいことですが、明らかに問題は2行目です
......実際には例外ではないものに例外を使用することについての疑問もあります。(4行目)では 、 データを評価してすべてを1つにまとめる
パターンを作成します。 -いくつかの「アーキテクチャクラス」を作成することは避けてください。このような単純なタスクでは、クラスの爆発的な増加(次のデザインパターンのJavaスタイルの原則imhoで誇張する場合の典型的なもの)を避けたいと思います。-できるだけ早く。 -...エレガントです:)


4

3 に答える 3

2

答えは今の私の直感に基づいているので、完璧ではないかもしれませんが、一方で、ほとんどの設計ソリューションはそうではありません。

追加のクラスを1つだけ作成し、それをファクトリなどと呼びます。次に、このクラスですべての構造を実行します。実行時(プログラムの開始時にコールバックを実行することによって)、またはさらに良いことに、可変個引数テンプレートの特性によって、Bの派生の可能なインスタンス化で初期化できる必要があります。

template<class ... RegisteredBImplementations>
class CFactory
{
    B* Create (dataset const& d)
    {
        // some magical meta-ifs to create compile time conditions
        // or for (auto& registered_type : registered types), and then choose one
        return new T(d);
    }
}

次に、Aはこのクラスのインスタンスを使用して、ポインターを適切に初期化できます。

for (auto& dataset : datasets)
{
    m_BPtrs.emplace_back( std::unique_ptr<dataset> (m_FactoryInstance.Create(dataset)) );
}

このソリューションの主なポイントは、クラスAが「B」オブジェクトを効果的に管理し、それらの適切な構築を他のクラスに任せることです。それらは効果的に分離されており、新しいB実装の追加は、CFactoryではなく、でのみ変更されることを意味しAます。

于 2012-08-28T10:01:56.970 に答える
1

最も簡単な解決策は、ファクトリメソッドに委任することです。

std::unique_ptr<B> build(DataSet const& ds) {
    if (ds.property() == value) {
        return std::unique_ptr<B>(new D(ds));
    }
    return std::unique_ptr<B>(new C(ds));
}

次にA、の宣言にのみ依存する必要がありbuildます。

于 2012-08-28T12:51:50.643 に答える
1

擬似コードは解決策を提案します。の使用は、入力としてを受け取り、出力としてを返すbiファクトリ関数にすぎません。したがって、実際には、オブジェクトのコレクションから取得する必要があります。datasetB*bistd::function<B* (dataset)>

これらのファクトリが「条件付き」ファクトリのみであることを要求するのは簡単です。有効なオブジェクトを返す場合と返さない場合があり、nullptr代わりに返されます。これにより、例外を回避でき、使用目的により忠実になります。

于 2012-08-28T14:01:48.150 に答える